<!DOCTYPE html>
<html lang="en">
    <head>
  <!-- 元数据 -->
  <meta charset="utf-8">
  <link rel="icon" href="https://gitee.com/cuishikang/tmp/raw/master/img/boke.png">
  <title>RABC权限学习记录文档 | 小崔的博客</title>
  <meta name="author" content="cuishikang" />
  <meta http-equiv="Cache-Control" content="no-transform" />
  <meta http-equiv="Cache-Control" content="no-siteapp" />
  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  <meta name="robots" content="index,follow" />
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1" />
  <meta name="format-detection" content="telphone=no, email=no" />
  
    <meta name="keywords" content="RABC, axios" />
  
  <meta name="description" content="::: tip 介绍 RABC权限学习记录文档 从头到尾学习文档:::">
<meta property="og:type" content="article">
<meta property="og:title" content="RABC权限学习记录文档">
<meta property="og:url" content="https://cuishikang.gitee.io/2022/01/11/Vue_RBAC/1_RBAC/index.html">
<meta property="og:site_name" content="小崔的博客">
<meta property="og:description" content="::: tip 介绍 RABC权限学习记录文档 从头到尾学习文档:::">
<meta property="og:locale" content="en_US">
<meta property="og:image" content="https://gitee.com/cuishikang/tmp/raw/master/img/boke.png">
<meta property="article:published_time" content="2022-01-10T16:00:00.000Z">
<meta property="article:modified_time" content="2022-02-19T10:22:58.548Z">
<meta property="article:author" content="cuishikang">
<meta property="article:tag" content="axios">
<meta property="article:tag" content="RABC">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="https://gitee.com/cuishikang/tmp/raw/master/img/boke.png">
<meta name="twitter:site" content="@null">
  
  <!-- 站点验证相关 -->
  
    
    
    
  
  <!-- 样式表文件 -->
  <link rel="stylesheet" id="kratos-css" href="/css/kratosr.min.css" type="text/css" media="all">
  
    <link rel="stylesheet" id="highlight-css" href="/css/highlight/night-eighties.min.css" type="text/css" media="all">
  
  
  <link rel="stylesheet" id="fontawe-css" href="https://unpkg.com/font-awesome@4.7.0/css/font-awesome.min.css" type="text/css" media="all">
  <link rel="stylesheet" id="nprogress-css" href="https://unpkg.com/nprogress@0.2.0/nprogress.css" type="text/css" media="all">
  
  
    <link rel="stylesheet" href="https://unpkg.com/aplayer@1.10.1/dist/APlayer.min.css">
  
  
    <link rel="stylesheet" href="https://unpkg.com/@fancyapps/fancybox@3.5.7/dist/jquery.fancybox.min.css">
  
  
    <link rel="stylesheet" id="darkmode-css" href="/css/kr-dark.min.css" type="text/css" media="all">
  
  <!-- 不得不预先加载的一些JS文件 -->
  <script src="https://unpkg.com/jquery@3.6.0/dist/jquery.min.js"></script>
  
    <script src="https://unpkg.com/qrcode_js@1.0.0/qrcode.min.js"></script>
  
  
  <style>
    
      .kratos-cover.kratos-cover-2 {
        background-image: url('/images/banner.webp');
      }
    
    
      @media(min-width:768px) {
        body.custom-background {
          background-image: url('/images/bg.webp');
        }
      }
    
  </style>
  
<meta name="generator" content="Hexo 6.0.0"></head>


    <body class="custom-background">
        <div id="kratos-wrapper">
    <div id="kratos-page">
        <div id="kratos-header">
            <header id="kratos-desktop-topnav" class="kratos-topnav">
                <div class="container">
                    <div class="nav-header">
                        <nav id="kratos-menu-wrap">
                            <ul id="kratos-primary-menu" class="sf-menu">
                                
                                    
                                        <li><a href="/"><i class="fa fa-home"></i>首页</a></li>
                                    
                                
                                    
                                        <li><a href="/archives/"><i class="fa fa-file"></i>档案馆</a></li>
                                    
                                
                                    
                                        <li><a href="/friends/"><i class="fa fa-paw"></i>好伙伴</a></li>
                                    
                                
                                    
                                        <li>
                                            <a><i class="fa fa-link"></i>关于本人</a>
                                            <ul class="sub-menu">
                                                
                                                    
                                                
                                                    
                                                        <li><a target="_blank" rel="noopener" href="https://gitee.com/cuishikang"><i class="fa fa-git"></i>码云</a></li>
                                                    
                                                
                                                    
                                                        <li><a target="_blank" rel="noopener" href="https://gitee.com/cuishikang/tmp/raw/master/img/2201645358312_.pic.jpg"><i class="fa fa-weixin"></i>微信</a></li>
                                                    
                                                
                                                    
                                                        <li><a target="_blank" rel="noopener" href="https://www.zhihu.com/people/fu-xi-ting-67-17-5"><i class="fa  fa-search"></i>知乎</a></li>
                                                    
                                                
                                                    
                                                        <li><a href="http://cuishikang.gitee.io/my_resume/#/"><i class="fa  fa-file-o"></i>简历</a></li>
                                                    
                                                
                                            </ul>
                                        </li>
                                    
                                
                            </ul>
                        </nav>
                    </div>
                </div>
            </header>
            <header id="kratos-mobile-topnav" class="kratos-topnav">
                <div class="container">
                    <div class="color-logo"><a href="/">小崔的博客</a></div>
                    <div class="nav-toggle">
                        <a class="kratos-nav-toggle js-kratos-nav-toggle">
                            <i></i>
                        </a>
                    </div>
                </div>
            </header>
        </div>
        <div class="kratos-start kratos-hero-2">
            <!-- <div class="kratos-overlay"></div> -->
            <div class="kratos-cover kratos-cover-2 text-center">
                <div class="desc desc2 animate-box">
                    <a href="/">
                        <h2>小崔的博客</h2> <br />
                        <span></span>
                    </a>
                </div>
            </div>
        </div>

        <div id="kratos-blog-post">
            <div class="container">
                <div id="main" class="row">
                    

        

            <section class="col-md-8">

        

            <article>
    <div class="kratos-hentry kratos-post-inner clearfix">
        <header class="kratos-entry-header">
            
                <h1 class="kratos-entry-title text-center">RABC权限学习记录文档</h1>
            
            
            <ul class="kratos-post-meta text-center">
                <li><i class="fa fa-calendar"></i> 2022-01-11</li>
                <li><i class="fa fa-user"></i> 作者 cuishikang</li>
                <li>
                    <i class="fa fa-edit"></i> 
                    
                    
                        ~42.30K
                    
                    字
                </li>
                
            </ul>
        </header>
        <div class="kratos-post-content">
            <div id="expire-alert" class="alert alert-warning hidden" role="alert">
                本文最后编辑于 <time datetime="1645266178548"></time> 前，其中的内容可能需要更新。
            </div>
            
            <hr />
            <p>::: tip 介绍</p>
<p>RABC权限学习记录文档 从头到尾学习文档<br><br>:::</p>
<span id="more"></span>

<h2 id="权限流程图"><a href="#权限流程图" class="headerlink" title="权限流程图"></a>权限流程图</h2><ul>
<li><p><a target="_blank" rel="noopener" href="https://jinyanlong-1305883696.cos.ap-hongkong.myqcloud.com/%E8%AE%BF%E9%97%AE%E8%AE%A4%E8%AF%81%E6%B5%81%E7%A8%8B.pdf">整体权限的流程总结图pdf</a></p>
</li>
<li><p><a target="_blank" rel="noopener" href="https://gitee.com/liu_kaili/mine-project-advanced-revision">本地仓库地址</a></p>
</li>
<li><p><a target="_blank" rel="noopener" href="http://element-admin.ynitmk.cn/">项目体验地址</a>  账户 admin  密码 1234</p>
</li>
<li><p>前端主体权限流程图(前端流程)</p>
</li>
</ul>
<p><img src="https://jinyanlong-1305883696.cos.ap-hongkong.myqcloud.com/image-20211208172131082.png" alt="image-20211208172131082"></p>
<ul>
<li>后端权限流程图(表结构 仅供参考)</li>
</ul>
<p><img src="https://jinyanlong-1305883696.cos.ap-hongkong.myqcloud.com/image-20211213101322386.png" alt="image-20211213101322386"></p>
<h2 id="权限学习地址"><a href="#权限学习地址" class="headerlink" title="权限学习地址"></a>权限学习地址</h2><ul>
<li>我是通过<a target="_blank" rel="noopener" href="https://ke.qq.com/course/3451173">腾讯课堂</a>来学习的权限管理内容 所有的笔记都按照其授课内容记录的 请先浏览该项目后 符合项目设计需求后 再继续浏览本记录</li>
</ul>
<h2 id="权限准备工作"><a href="#权限准备工作" class="headerlink" title="权限准备工作"></a>权限准备工作</h2><blockquote>
<p>后端兄弟需要怎么配合你呢</p>
</blockquote>
<ul>
<li><p>首先 需要后端把权限按照你需要的格式返回给你</p>
<ul>
<li><code>roles</code> 是用户拥有权限的合集 前端是通过<code>roles</code>来判断用户是否具备路由权限和路由按钮权限(元素) <font color = #ff3040>注意: 必须是一个数组格式 </font></li>
</ul>
<p><img src="https://jinyanlong-1305883696.cos.ap-hongkong.myqcloud.com/image-20211212191435998.png" alt="image-20211212191435998"></p>
<ul>
<li>然后 你需要让后端生成全部动态路由菜单  <font color = #ff3040>注意: 必须让后端这样做</font><ul>
<li>这里的动态路由菜单就是路由权限 前端会通过vue element admin 中提供的路由权限架构实现路由的整体权限控制 <ul>
<li>vue element admin 提供了meta对象 里面包含<code>roles</code> 就是控制路由权限的凭证</li>
</ul>
</li>
</ul>
</li>
</ul>
<p><img src="https://jinyanlong-1305883696.cos.ap-hongkong.myqcloud.com/image-20220111094334915.png" alt="image-20211212191525037"></p>
<ul>
<li>其次 是路由按钮(元素)的权限 在第二阶段中</li>
</ul>
</li>
</ul>
<blockquote>
<p>前端准备工作</p>
</blockquote>
<ul>
<li>如果我们用的是<a target="_blank" rel="noopener" href="https://panjiachen.github.io/vue-element-admin-site/zh/">vue-element-admin</a> 框架 就必须要要知道登录和权限流程</li>
</ul>
<ol start="0">
<li><p>二次封装一个 axios请求库 <code>request.js</code> (按需)</p>
<ul>
<li>需要qs包 qs是一个url参数转化（parse和stringify）的js库</li>
</ul>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm i qs</span><br></pre></td></tr></table></figure>

<ul>
<li>这里是按需封装 如果你有需要的话 </li>
<li>请求拦截器往里面塞了请求头token</li>
</ul>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br><span class="line">196</span><br><span class="line">197</span><br><span class="line">198</span><br><span class="line">199</span><br><span class="line">200</span><br><span class="line">201</span><br><span class="line">202</span><br><span class="line">203</span><br><span class="line">204</span><br><span class="line">205</span><br><span class="line">206</span><br><span class="line">207</span><br><span class="line">208</span><br><span class="line">209</span><br><span class="line">210</span><br><span class="line">211</span><br><span class="line">212</span><br><span class="line">213</span><br><span class="line">214</span><br><span class="line">215</span><br><span class="line">216</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> axios <span class="keyword">from</span> <span class="string">&#x27;axios&#x27;</span></span><br><span class="line"><span class="keyword">import</span> &#123; <span class="title class_">MessageBox</span>, <span class="title class_">Message</span> &#125; <span class="keyword">from</span> <span class="string">&#x27;element-ui&#x27;</span></span><br><span class="line"><span class="keyword">import</span> store <span class="keyword">from</span> <span class="string">&#x27;@/store&#x27;</span></span><br><span class="line"><span class="keyword">import</span> &#123; getToken &#125; <span class="keyword">from</span> <span class="string">&#x27;@/utils/auth&#x27;</span></span><br><span class="line"><span class="keyword">import</span> qs <span class="keyword">from</span> <span class="string">&#x27;qs&#x27;</span></span><br><span class="line"><span class="comment">// create an axios instance</span></span><br><span class="line"><span class="keyword">const</span> service = axios.<span class="title function_">create</span>(&#123;</span><br><span class="line">  <span class="comment">// 默认url基本路径</span></span><br><span class="line">  <span class="attr">baseURL</span>: <span class="string">&#x27;http://42.193.158.170:8089&#x27;</span>,</span><br><span class="line">  <span class="comment">// withCredentials: true, // send cookies when cross-domain requests</span></span><br><span class="line">  <span class="attr">timeout</span>: <span class="number">5000</span> <span class="comment">// request timeout</span></span><br><span class="line">&#125;)</span><br><span class="line"></span><br><span class="line"><span class="comment">// request interceptor</span></span><br><span class="line"><span class="comment">// 发送请求之前的拦截器</span></span><br><span class="line">service.<span class="property">interceptors</span>.<span class="property">request</span>.<span class="title function_">use</span>(</span><br><span class="line">  <span class="function"><span class="params">config</span> =&gt;</span> &#123;</span><br><span class="line">    <span class="comment">// do something before request is sent</span></span><br><span class="line">    <span class="comment">// 从store里面获取token，如果token存在，</span></span><br><span class="line">    <span class="comment">// 把token添加到请求的头部Headers里面</span></span><br><span class="line">    <span class="keyword">if</span> (store.<span class="property">getters</span>.<span class="property">token</span>) &#123;</span><br><span class="line">      <span class="comment">// let each request carry token</span></span><br><span class="line">      <span class="comment">// [&#x27;X-Token&#x27;] is a custom headers key</span></span><br><span class="line">      <span class="comment">// please modify it according to the actual situation</span></span><br><span class="line">      <span class="comment">// 把token添加到请求的头部</span></span><br><span class="line">      [<span class="string">&#x27;token&#x27;</span>] = <span class="title function_">getToken</span>()</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> config</span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="function"><span class="params">error</span> =&gt;</span> &#123;</span><br><span class="line">    <span class="comment">// do something with request error</span></span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(error) <span class="comment">// for debug</span></span><br><span class="line">    <span class="keyword">return</span> <span class="title class_">Promise</span>.<span class="title function_">reject</span>(error)</span><br><span class="line">  &#125;</span><br><span class="line">)</span><br><span class="line"></span><br><span class="line"><span class="comment">// response interceptor</span></span><br><span class="line"><span class="comment">// 请求返回之后的拦截器</span></span><br><span class="line">service.<span class="property">interceptors</span>.<span class="property">response</span>.<span class="title function_">use</span>(</span><br><span class="line">  <span class="comment">/**</span></span><br><span class="line"><span class="comment">   * If you want to get http information such as headers or status</span></span><br><span class="line"><span class="comment">   * Please return  response =&gt; response</span></span><br><span class="line"><span class="comment">  */</span></span><br><span class="line"></span><br><span class="line">  <span class="comment">/**</span></span><br><span class="line"><span class="comment">   * Determine the request status by custom code</span></span><br><span class="line"><span class="comment">   * Here is just an example</span></span><br><span class="line"><span class="comment">   * You can also judge the status by HTTP Status Code</span></span><br><span class="line"><span class="comment">   */</span></span><br><span class="line">  <span class="function"><span class="params">response</span> =&gt;</span> &#123;</span><br><span class="line">    <span class="keyword">const</span> res = response.<span class="property">data</span></span><br><span class="line">    <span class="comment">// console.log(response)</span></span><br><span class="line">    <span class="comment">// console.log(res)</span></span><br><span class="line">    <span class="comment">// if the custom code is not 20000, it is judged as an error.</span></span><br><span class="line">    <span class="keyword">if</span> (res.<span class="property">code</span> !== <span class="number">200</span>) &#123;</span><br><span class="line">      <span class="comment">// 验证码处理：返回的是arraybuffer,需要转车base64</span></span><br><span class="line">      <span class="comment">// 1.把arraybuffer转换成二进制字符</span></span><br><span class="line">      <span class="comment">// 2.把二进制字符转换为base64 (btoa方法)字符给img使用</span></span><br><span class="line">      <span class="keyword">const</span> indexs = response.<span class="property">config</span>.<span class="property">responseType</span></span><br><span class="line">      <span class="keyword">if</span> (indexs === <span class="string">&#x27;arraybuffer&#x27;</span>) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="title class_">Promise</span>.<span class="title function_">resolve</span>(</span><br><span class="line">          <span class="string">&#x27;data:image/png;base64,&#x27;</span> +</span><br><span class="line">          <span class="title function_">btoa</span>(</span><br><span class="line">            <span class="keyword">new</span> <span class="title class_">Uint8Array</span>(res).<span class="title function_">reduce</span>(</span><br><span class="line">              <span class="function">(<span class="params">data, byte</span>) =&gt;</span> data + <span class="title class_">String</span>.<span class="title function_">fromCharCode</span>(byte), <span class="string">&#x27;&#x27;</span></span><br><span class="line">            )</span><br><span class="line">          )</span><br><span class="line">        )</span><br><span class="line">      &#125;</span><br><span class="line">      <span class="title class_">Message</span>(&#123;</span><br><span class="line">        <span class="attr">message</span>: res.<span class="property">msg</span> || <span class="string">&#x27;服务器出错&#x27;</span>,</span><br><span class="line">        <span class="attr">type</span>: <span class="string">&#x27;error&#x27;</span>,</span><br><span class="line">        <span class="attr">duration</span>: <span class="number">5</span> * <span class="number">1000</span></span><br><span class="line">      &#125;)</span><br><span class="line"></span><br><span class="line">      <span class="comment">// 50008: Illegal token; 50012: Other clients logged in; 50014: Token expired;</span></span><br><span class="line">      <span class="keyword">if</span> (res.<span class="property">code</span> === <span class="number">600</span> || res.<span class="property">code</span> === <span class="number">50012</span> || res.<span class="property">code</span> === <span class="number">50014</span>) &#123;</span><br><span class="line">        <span class="comment">// to re-login</span></span><br><span class="line">        <span class="title class_">MessageBox</span>.<span class="title function_">confirm</span>(<span class="string">&#x27;用户登录信息过期，请重新登录！&#x27;</span>, <span class="string">&#x27;系统提示&#x27;</span>, &#123;</span><br><span class="line">          <span class="attr">confirmButtonText</span>: <span class="string">&#x27;登录&#x27;</span>,</span><br><span class="line">          <span class="attr">cancelButtonText</span>: <span class="string">&#x27;取消&#x27;</span>,</span><br><span class="line">          <span class="attr">type</span>: <span class="string">&#x27;warning&#x27;</span></span><br><span class="line">        &#125;).<span class="title function_">then</span>(<span class="function">() =&gt;</span> &#123;</span><br><span class="line">          store.<span class="title function_">dispatch</span>(<span class="string">&#x27;user/resetToken&#x27;</span>).<span class="title function_">then</span>(<span class="function">() =&gt;</span> &#123;</span><br><span class="line">            location.<span class="title function_">reload</span>()</span><br><span class="line">          &#125;)</span><br><span class="line">        &#125;)</span><br><span class="line">      &#125;</span><br><span class="line">      <span class="keyword">return</span> <span class="title class_">Promise</span>.<span class="title function_">reject</span>(<span class="keyword">new</span> <span class="title class_">Error</span>(res.<span class="property">msg</span> || <span class="string">&#x27;服务器出错&#x27;</span>))</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">      <span class="keyword">return</span> res</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="function"><span class="params">error</span> =&gt;</span> &#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&#x27;err&#x27;</span> + error) <span class="comment">// for debug</span></span><br><span class="line">    <span class="title class_">Message</span>(&#123;</span><br><span class="line">      <span class="attr">message</span>: error.<span class="property">msg</span> || <span class="string">&#x27;服务器出错&#x27;</span>,</span><br><span class="line">      <span class="attr">type</span>: <span class="string">&#x27;error&#x27;</span>,</span><br><span class="line">      <span class="attr">duration</span>: <span class="number">5</span> * <span class="number">1000</span></span><br><span class="line">    &#125;)</span><br><span class="line">    <span class="keyword">return</span> <span class="title class_">Promise</span>.<span class="title function_">reject</span>(error)</span><br><span class="line">  &#125;</span><br><span class="line">)</span><br><span class="line"></span><br><span class="line"><span class="comment">// 请求方法</span></span><br><span class="line"><span class="keyword">const</span> http = &#123;</span><br><span class="line">  post (url, params) &#123;</span><br><span class="line">    <span class="keyword">return</span> service.<span class="title function_">post</span>(url, params, &#123;</span><br><span class="line">      <span class="attr">transformRequest</span>: [<span class="function">(<span class="params">params</span>) =&gt;</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="title class_">JSON</span>.<span class="title function_">stringify</span>(params)</span><br><span class="line">      &#125;],</span><br><span class="line">      <span class="attr">headers</span>: &#123;</span><br><span class="line">        <span class="string">&#x27;Content-Type&#x27;</span>: <span class="string">&#x27;application/json&#x27;</span></span><br><span class="line">      &#125;</span><br><span class="line">    &#125;)</span><br><span class="line">  &#125;,</span><br><span class="line">  put (url, params) &#123;</span><br><span class="line">    <span class="keyword">return</span> service.<span class="title function_">put</span>(url, params, &#123;</span><br><span class="line">      <span class="attr">transformRequest</span>: [<span class="function">(<span class="params">params</span>) =&gt;</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="title class_">JSON</span>.<span class="title function_">stringify</span>(params)</span><br><span class="line">      &#125;],</span><br><span class="line">      <span class="attr">headers</span>: &#123;</span><br><span class="line">        <span class="string">&#x27;Content-Type&#x27;</span>: <span class="string">&#x27;application/json&#x27;</span></span><br><span class="line">      &#125;</span><br><span class="line">    &#125;)</span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="comment">// parm =&gt;  &#123;id:10&#125;</span></span><br><span class="line">  <span class="comment">// http://localhost:8089/api/user?id=10</span></span><br><span class="line">  get (url, params) &#123;</span><br><span class="line">    <span class="keyword">return</span> service.<span class="title function_">get</span>(url, &#123;</span><br><span class="line">      <span class="attr">params</span>: params,</span><br><span class="line">      <span class="attr">paramsSerializer</span>: <span class="function">(<span class="params">params</span>) =&gt;</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> qs.<span class="title function_">stringify</span>(params)</span><br><span class="line">      &#125;</span><br><span class="line">    &#125;)</span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="comment">// parm =&gt;  &#123;id:10&#125;</span></span><br><span class="line">  <span class="comment">// http://localhost:8089/api/user/10</span></span><br><span class="line">  getRestApi (url, params) &#123;</span><br><span class="line">    <span class="keyword">let</span> _params</span><br><span class="line">    <span class="keyword">if</span> (<span class="title class_">Object</span>.<span class="title function_">is</span>(params, <span class="literal">undefined</span> || <span class="literal">null</span>)) &#123;</span><br><span class="line">      _params = <span class="string">&#x27;&#x27;</span></span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">      _params = <span class="string">&#x27;/&#x27;</span></span><br><span class="line">      <span class="keyword">for</span> (<span class="keyword">const</span> key <span class="keyword">in</span> params) &#123;</span><br><span class="line">        <span class="variable language_">console</span>.<span class="title function_">log</span>(key)</span><br><span class="line">        <span class="variable language_">console</span>.<span class="title function_">log</span>(params[key])</span><br><span class="line">        <span class="comment">// eslint-disable-next-line no-prototype-builtins</span></span><br><span class="line">        <span class="keyword">if</span> (params.<span class="title function_">hasOwnProperty</span>(key) &amp;&amp; params[key] !== <span class="literal">null</span> &amp;&amp; params[key] !== <span class="string">&#x27;&#x27;</span>) &#123;</span><br><span class="line">          _params += <span class="string">`<span class="subst">$&#123;params[key]&#125;</span>/`</span></span><br><span class="line">        &#125;</span><br><span class="line">      &#125;</span><br><span class="line">      <span class="comment">// 去掉参数最后一位?</span></span><br><span class="line">      _params = _params.<span class="title function_">substr</span>(<span class="number">0</span>, _params.<span class="property">length</span> - <span class="number">1</span>)</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(_params)</span><br><span class="line">    <span class="keyword">if</span> (_params) &#123;</span><br><span class="line">      <span class="keyword">return</span> service.<span class="title function_">get</span>(<span class="string">`<span class="subst">$&#123;url&#125;</span><span class="subst">$&#123;_params&#125;</span>`</span>)</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">      <span class="keyword">return</span> service.<span class="title function_">get</span>(url)</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="comment">// parm =&gt;  &#123;id:10&#125;</span></span><br><span class="line">  <span class="comment">// http://localhost:8089/api/user/10</span></span><br><span class="line">  <span class="keyword">delete</span> (url, params) &#123;</span><br><span class="line">    <span class="keyword">let</span> _params</span><br><span class="line">    <span class="keyword">if</span> (<span class="title class_">Object</span>.<span class="title function_">is</span>(params, <span class="literal">undefined</span> || <span class="literal">null</span>)) &#123;</span><br><span class="line">      _params = <span class="string">&#x27;&#x27;</span></span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">      _params = <span class="string">&#x27;/&#x27;</span></span><br><span class="line">      <span class="keyword">for</span> (<span class="keyword">const</span> key <span class="keyword">in</span> params) &#123;</span><br><span class="line">        <span class="comment">// eslint-disable-next-line no-prototype-builtins</span></span><br><span class="line">        <span class="keyword">if</span> (params.<span class="title function_">hasOwnProperty</span>(key) &amp;&amp; params[key] !== <span class="literal">null</span> &amp;&amp; params[key] !== <span class="string">&#x27;&#x27;</span>) &#123;</span><br><span class="line">          _params += <span class="string">`<span class="subst">$&#123;params[key]&#125;</span>/`</span></span><br><span class="line">        &#125;</span><br><span class="line">      &#125;</span><br><span class="line">      <span class="comment">// 去掉参数最后一位?</span></span><br><span class="line">      _params = _params.<span class="title function_">substr</span>(<span class="number">0</span>, _params.<span class="property">length</span> - <span class="number">1</span>)</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span> (_params) &#123;</span><br><span class="line">      <span class="keyword">return</span> service.<span class="title function_">delete</span>(<span class="string">`<span class="subst">$&#123;url&#125;</span><span class="subst">$&#123;_params&#125;</span>`</span>).<span class="title function_">catch</span>(<span class="function"><span class="params">err</span> =&gt;</span> &#123;</span><br><span class="line">        <span class="title class_">Message</span>.<span class="title function_">error</span>(err.<span class="property">msg</span>)</span><br><span class="line">        <span class="keyword">return</span> <span class="title class_">Promise</span>.<span class="title function_">reject</span>(err)</span><br><span class="line">      &#125;)</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">      <span class="keyword">return</span> service.<span class="title function_">delete</span>(url).<span class="title function_">catch</span>(<span class="function"><span class="params">err</span> =&gt;</span> &#123;</span><br><span class="line">        <span class="title class_">Message</span>.<span class="title function_">error</span>(err.<span class="property">msg</span>)</span><br><span class="line">        <span class="keyword">return</span> <span class="title class_">Promise</span>.<span class="title function_">reject</span>(err)</span><br><span class="line">      &#125;)</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;,</span><br><span class="line">  upload (url, params) &#123;</span><br><span class="line">    <span class="keyword">return</span> service.<span class="title function_">post</span>(url, params, &#123;</span><br><span class="line">      <span class="attr">headers</span>: &#123;</span><br><span class="line">        <span class="string">&#x27;Content-Type&#x27;</span>: <span class="string">&#x27;multipart/form-data&#x27;</span></span><br><span class="line">      &#125;</span><br><span class="line">    &#125;)</span><br><span class="line">  &#125;,</span><br><span class="line">  login (url, params) &#123;</span><br><span class="line">    <span class="keyword">return</span> service.<span class="title function_">post</span>(url, params, &#123;</span><br><span class="line">      <span class="attr">transformRequest</span>: [<span class="function">(<span class="params">params</span>) =&gt;</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> qs.<span class="title function_">stringify</span>(params)</span><br><span class="line">      &#125;],</span><br><span class="line">      <span class="attr">headers</span>: &#123;</span><br><span class="line">        <span class="string">&#x27;Content-Type&#x27;</span>: <span class="string">&#x27;application/x-www-form-urlencoded&#x27;</span></span><br><span class="line">      &#125;</span><br><span class="line">    &#125;)</span><br><span class="line">  &#125;,</span><br><span class="line">  getImage (url) &#123;</span><br><span class="line">    <span class="keyword">return</span> service.<span class="title function_">post</span>(url, <span class="literal">null</span>, &#123;</span><br><span class="line">      <span class="attr">responseType</span>: <span class="string">&#x27;arraybuffer&#x27;</span></span><br><span class="line">    &#125;)</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> http</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<ul>
<li>封装后 api请求的格式 <code>api.js</code><ul>
<li>二次封装axios后 我们直接async awite</li>
</ul>
</li>
</ul>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> http <span class="keyword">from</span> <span class="string">&#x27;@/utils/requestStudent&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 登录</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">async</span> <span class="keyword">function</span> <span class="title function_">login</span> (parms) &#123;</span><br><span class="line">  <span class="keyword">return</span> <span class="keyword">await</span> http.<span class="title function_">login</span>(<span class="string">&#x27;/api/user/login&#x27;</span>, parms)</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 获取用户信息和权限信息</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">async</span> <span class="keyword">function</span> <span class="title function_">getInfo</span> () &#123;</span><br><span class="line">  <span class="keyword">return</span> <span class="keyword">await</span> http.<span class="title function_">get</span>(<span class="string">&#x27;/api/sysUser/getInfo&#x27;</span>)</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 获取全部的动态路由</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">async</span> <span class="keyword">function</span> <span class="title function_">getMenuList</span> () &#123;</span><br><span class="line">  <span class="keyword">return</span> <span class="keyword">await</span> http.<span class="title function_">get</span>(<span class="string">&#x27;/api/sysUser/getMenuList&#x27;</span>)</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 获取用户列表</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">async</span> <span class="keyword">function</span> <span class="title function_">getUserListApi</span> (parm) &#123;</span><br><span class="line">  <span class="keyword">return</span> <span class="keyword">await</span> http.<span class="title function_">getRestApi</span>(<span class="string">&#x27;/api/user/list&#x27;</span>, parm)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</li>
<li><p>登录实际上是再vuex中进行的 通过vuex来获取的登录信息(用户拥有的权限集合) 和 动态路由信息</p>
<ul>
<li>登录信息(用户拥有的权限集合) <code>Vuex中 user.js</code><ul>
<li>这里的 <code>login, logout, getInfo</code> 可以替换成自己的接口数据</li>
</ul>
</li>
</ul>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> &#123; getToken, setToken, removeToken &#125; <span class="keyword">from</span> <span class="string">&#x27;@/utils/auth&#x27;</span></span><br><span class="line"><span class="keyword">import</span> router, &#123; resetRouter &#125; <span class="keyword">from</span> <span class="string">&#x27;@/router&#x27;</span></span><br><span class="line"><span class="keyword">import</span> &#123; login, getInfo &#125; <span class="keyword">from</span> <span class="string">&#x27;@/api/students/student&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> state = &#123;</span><br><span class="line">  <span class="comment">// 通过cookie获取token</span></span><br><span class="line">  <span class="attr">token</span>: <span class="title function_">getToken</span>(),</span><br><span class="line">  <span class="comment">// 用户名</span></span><br><span class="line">  <span class="attr">name</span>: <span class="string">&#x27;&#x27;</span>,</span><br><span class="line">  <span class="comment">// 用户头像</span></span><br><span class="line">  <span class="attr">avatar</span>: <span class="string">&#x27;&#x27;</span>,</span><br><span class="line">  <span class="comment">// 用户简介</span></span><br><span class="line">  <span class="attr">introduction</span>: <span class="string">&#x27;&#x27;</span>,</span><br><span class="line">  <span class="comment">// 用户拥有的权限集合</span></span><br><span class="line">  <span class="attr">roles</span>: [],</span><br><span class="line">  <span class="comment">// 用户id</span></span><br><span class="line">  <span class="attr">userId</span>: <span class="string">&#x27;&#x27;</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> mutations = &#123;</span><br><span class="line">  <span class="attr">SET_TOKEN</span>: <span class="function">(<span class="params">state, token</span>) =&gt;</span> &#123;</span><br><span class="line">    state.<span class="property">token</span> = token</span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="attr">SET_INTRODUCTION</span>: <span class="function">(<span class="params">state, introduction</span>) =&gt;</span> &#123;</span><br><span class="line">    state.<span class="property">introduction</span> = introduction</span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="attr">SET_NAME</span>: <span class="function">(<span class="params">state, name</span>) =&gt;</span> &#123;</span><br><span class="line">    state.<span class="property">name</span> = name</span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="attr">SET_USERUID</span>: <span class="function">(<span class="params">state, userId</span>) =&gt;</span> &#123;</span><br><span class="line">    state.<span class="property">userId</span> = userId</span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="attr">SET_AVATAR</span>: <span class="function">(<span class="params">state, avatar</span>) =&gt;</span> &#123;</span><br><span class="line">    state.<span class="property">avatar</span> = avatar</span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="attr">SET_ROLES</span>: <span class="function">(<span class="params">state, roles</span>) =&gt;</span> &#123;</span><br><span class="line">    state.<span class="property">roles</span> = roles</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> actions = &#123;</span><br><span class="line">  <span class="comment">// user login  用户登录 用作用户登录</span></span><br><span class="line">  login (&#123; commit &#125;, userInfo) &#123;</span><br><span class="line">    <span class="comment">// 解构出用户名和密码</span></span><br><span class="line">    <span class="keyword">const</span> &#123; username, password, code &#125; = userInfo</span><br><span class="line">    <span class="comment">// 调用promise方法登录</span></span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Promise</span>(<span class="function">(<span class="params">resolve, reject</span>) =&gt;</span> &#123;</span><br><span class="line">      <span class="comment">// 调用api/user里面的login方法</span></span><br><span class="line">      <span class="title function_">login</span>(&#123;</span><br><span class="line">        <span class="comment">// 用户登录的信息</span></span><br><span class="line">        <span class="attr">username</span>: username.<span class="title function_">trim</span>(),</span><br><span class="line">        <span class="attr">password</span>: password,</span><br><span class="line">        <span class="attr">code</span>: code</span><br><span class="line">      &#125;).<span class="title function_">then</span>(<span class="function"><span class="params">response</span> =&gt;</span> &#123;</span><br><span class="line">        <span class="variable language_">console</span>.<span class="title function_">log</span>(response)</span><br><span class="line">        <span class="comment">// 结构token</span></span><br><span class="line">        <span class="keyword">const</span> &#123; token &#125; = response</span><br><span class="line">        <span class="comment">// 把后端返回的token存到vuex中</span></span><br><span class="line">        <span class="title function_">commit</span>(<span class="string">&#x27;SET_TOKEN&#x27;</span>, token)</span><br><span class="line">        <span class="comment">// 把后端返回的token存到cookies里面</span></span><br><span class="line">        <span class="title function_">setToken</span>(token)</span><br><span class="line">        <span class="title function_">resolve</span>()</span><br><span class="line">      &#125;).<span class="title function_">catch</span>(<span class="function"><span class="params">error</span> =&gt;</span> &#123;</span><br><span class="line">        <span class="title function_">reject</span>(error)</span><br><span class="line">      &#125;)</span><br><span class="line">    &#125;)</span><br><span class="line">  &#125;,</span><br><span class="line"></span><br><span class="line">  <span class="comment">// get user info 这里是路由信息</span></span><br><span class="line">  getInfo (&#123; commit, state &#125;) &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Promise</span>(<span class="function">(<span class="params">resolve, reject</span>) =&gt;</span> &#123;</span><br><span class="line">      <span class="comment">// 调用api/user里面的getInfo方法获取用户信息和权限信息</span></span><br><span class="line">      <span class="title function_">getInfo</span>(state.<span class="property">token</span>).<span class="title function_">then</span>(<span class="function"><span class="params">response</span> =&gt;</span> &#123;</span><br><span class="line">        <span class="variable language_">console</span>.<span class="title function_">log</span>(response)</span><br><span class="line">        <span class="comment">// 结构数据</span></span><br><span class="line">        <span class="keyword">const</span> &#123; data &#125; = response</span><br><span class="line">        <span class="keyword">if</span> (!data) &#123;</span><br><span class="line">          <span class="title function_">reject</span>(<span class="string">&#x27;Verification failed, please Login again.&#x27;</span>)</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">const</span> &#123; roles, name, introduction, id &#125; = data</span><br><span class="line"></span><br><span class="line">        <span class="comment">// roles must be a non-empty array</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">// roles必须是一个数组</span></span><br><span class="line">        <span class="keyword">if</span> (!roles || roles.<span class="property">length</span> &lt;= <span class="number">0</span>) &#123;</span><br><span class="line">          <span class="title function_">reject</span>(<span class="string">&#x27;getInfo: roles must be a non-null array!&#x27;</span>)</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">// 把权限字段放到sessionStorage里面</span></span><br><span class="line">        sessionStorage.<span class="title function_">setItem</span>(<span class="string">&#x27;codeList&#x27;</span>, <span class="title class_">JSON</span>.<span class="title function_">stringify</span>(roles))</span><br><span class="line">        <span class="comment">// 把roles存到store里面</span></span><br><span class="line">        <span class="title function_">commit</span>(<span class="string">&#x27;SET_ROLES&#x27;</span>, roles)</span><br><span class="line">        <span class="keyword">const</span> userImg = <span class="string">&#x27;https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif&#x27;</span></span><br><span class="line">        <span class="title function_">commit</span>(<span class="string">&#x27;SET_USERUID&#x27;</span>, id)</span><br><span class="line">        <span class="title function_">commit</span>(<span class="string">&#x27;SET_NAME&#x27;</span>, name)</span><br><span class="line">        <span class="title function_">commit</span>(<span class="string">&#x27;SET_AVATAR&#x27;</span>, userImg)</span><br><span class="line">        <span class="title function_">commit</span>(<span class="string">&#x27;SET_INTRODUCTION&#x27;</span>, introduction)</span><br><span class="line">        <span class="comment">// console.log(state)</span></span><br><span class="line">        <span class="title function_">resolve</span>(data)</span><br><span class="line">      &#125;).<span class="title function_">catch</span>(<span class="function"><span class="params">error</span> =&gt;</span> &#123;</span><br><span class="line">        <span class="variable language_">console</span>.<span class="title function_">log</span>(error)</span><br><span class="line">        <span class="title function_">reject</span>(error)</span><br><span class="line">      &#125;)</span><br><span class="line">    &#125;)</span><br><span class="line">  &#125;,</span><br><span class="line"></span><br><span class="line">  <span class="comment">// user logout</span></span><br><span class="line">  <span class="comment">// logout (&#123; commit, state, dispatch &#125;) &#123;</span></span><br><span class="line">  <span class="comment">//   return new Promise((resolve, reject) =&gt; &#123;</span></span><br><span class="line">  <span class="comment">//     logout(state.token).then(() =&gt; &#123;</span></span><br><span class="line">  <span class="comment">//       commit(&#x27;SET_TOKEN&#x27;, &#x27;&#x27;)</span></span><br><span class="line">  <span class="comment">//       commit(&#x27;SET_ROLES&#x27;, [])</span></span><br><span class="line">  <span class="comment">//       removeToken()</span></span><br><span class="line">  <span class="comment">//       resetRouter()</span></span><br><span class="line"></span><br><span class="line">  <span class="comment">//       // reset visited views and cached views</span></span><br><span class="line">  <span class="comment">//       // to fixed https://github.com/PanJiaChen/vue-element-admin/issues/2485</span></span><br><span class="line">  <span class="comment">//       dispatch(&#x27;tagsView/delAllViews&#x27;, null, &#123; root: true &#125;)</span></span><br><span class="line"></span><br><span class="line">  <span class="comment">//       resolve()</span></span><br><span class="line">  <span class="comment">//     &#125;).catch(error =&gt; &#123;</span></span><br><span class="line">  <span class="comment">//       reject(error)</span></span><br><span class="line">  <span class="comment">//     &#125;)</span></span><br><span class="line">  <span class="comment">//   &#125;)</span></span><br><span class="line">  <span class="comment">// &#125;,</span></span><br><span class="line"></span><br><span class="line">  <span class="comment">// remove token</span></span><br><span class="line">  resetToken (&#123; commit &#125;) &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Promise</span>(<span class="function"><span class="params">resolve</span> =&gt;</span> &#123;</span><br><span class="line">      <span class="title function_">commit</span>(<span class="string">&#x27;SET_TOKEN&#x27;</span>, <span class="string">&#x27;&#x27;</span>)</span><br><span class="line">      <span class="title function_">commit</span>(<span class="string">&#x27;SET_ROLES&#x27;</span>, [])</span><br><span class="line">      <span class="title function_">removeToken</span>()</span><br><span class="line">      <span class="title function_">resolve</span>()</span><br><span class="line">    &#125;)</span><br><span class="line">  &#125;,</span><br><span class="line"></span><br><span class="line">  <span class="comment">// dynamically modify permissions</span></span><br><span class="line">  <span class="keyword">async</span> changeRoles (&#123; commit, dispatch &#125;, role) &#123;</span><br><span class="line">    <span class="keyword">const</span> token = role + <span class="string">&#x27;-token&#x27;</span></span><br><span class="line"></span><br><span class="line">    <span class="title function_">commit</span>(<span class="string">&#x27;SET_TOKEN&#x27;</span>, token)</span><br><span class="line">    <span class="title function_">setToken</span>(token)</span><br><span class="line"></span><br><span class="line">    <span class="keyword">const</span> &#123; roles &#125; = <span class="keyword">await</span> <span class="title function_">dispatch</span>(<span class="string">&#x27;getInfo&#x27;</span>)</span><br><span class="line"></span><br><span class="line">    <span class="title function_">resetRouter</span>()</span><br><span class="line"></span><br><span class="line">    <span class="comment">// generate accessible routes map based on roles</span></span><br><span class="line">    <span class="keyword">const</span> accessRoutes = <span class="keyword">await</span> <span class="title function_">dispatch</span>(<span class="string">&#x27;permission/generateRoutes&#x27;</span>, roles, &#123; <span class="attr">root</span>: <span class="literal">true</span> &#125;)</span><br><span class="line">    <span class="comment">// dynamically add accessible routes</span></span><br><span class="line">    router.<span class="title function_">addRoutes</span>(accessRoutes)</span><br><span class="line"></span><br><span class="line">    <span class="comment">// reset visited views and cached views</span></span><br><span class="line">    <span class="title function_">dispatch</span>(<span class="string">&#x27;tagsView/delAllViews&#x27;</span>, <span class="literal">null</span>, &#123; <span class="attr">root</span>: <span class="literal">true</span> &#125;)</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> &#123;</span><br><span class="line">  <span class="attr">namespaced</span>: <span class="literal">true</span>,</span><br><span class="line">  state,</span><br><span class="line">  mutations,</span><br><span class="line">  actions</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<ul>
<li>动态路由信息 <code>Vuex中 permission.js</code><ul>
<li>这里是生成动态路由的内容</li>
<li><code>permission</code>非常关键 他会通过循环去判断 用户的<code>rolse</code>合集中的路由权限 是否和动态路由菜单匹配 然后生成权限动态路由</li>
</ul>
</li>
</ul>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> &#123; constantRoutes &#125; <span class="keyword">from</span> <span class="string">&#x27;@/router&#x27;</span></span><br><span class="line"><span class="keyword">import</span> &#123; getMenuList &#125; <span class="keyword">from</span> <span class="string">&#x27;@/api/students/student&#x27;</span></span><br><span class="line"><span class="keyword">import</span> <span class="title class_">Layout</span> <span class="keyword">from</span> <span class="string">&#x27;@/layout&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * Use meta.role to determine if the current user has permission</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> <span class="variable">roles</span></span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> <span class="variable">route</span></span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">hasPermission</span> (roles, route) &#123;</span><br><span class="line">  <span class="keyword">if</span> (route.<span class="property">meta</span> &amp;&amp; route.<span class="property">meta</span>.<span class="property">roles</span>) &#123;</span><br><span class="line">    <span class="keyword">return</span> roles.<span class="title function_">some</span>(<span class="function"><span class="params">role</span> =&gt;</span> route.<span class="property">meta</span>.<span class="property">roles</span>.<span class="title function_">includes</span>(role))</span><br><span class="line">  &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="literal">true</span></span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * Filter asynchronous routing tables by recursion</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> routes asyncRoutes</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> <span class="variable">roles</span></span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">function</span> <span class="title function_">filterAsyncRoutes</span> (routes, roles) &#123;</span><br><span class="line">  <span class="keyword">const</span> res = []</span><br><span class="line">  <span class="comment">// 循环每一个路由</span></span><br><span class="line">  routes.<span class="title function_">forEach</span>(<span class="function"><span class="params">route</span> =&gt;</span> &#123;</span><br><span class="line">    <span class="comment">// console.log(route)</span></span><br><span class="line">    <span class="keyword">const</span> tmp = &#123; ...route &#125;</span><br><span class="line">    <span class="comment">// console.log(tmp)</span></span><br><span class="line">    <span class="comment">// 判断是否有权限</span></span><br><span class="line">    <span class="keyword">if</span> (<span class="title function_">hasPermission</span>(roles, tmp)) &#123;</span><br><span class="line">      <span class="keyword">const</span> component = tmp.<span class="property">component</span></span><br><span class="line">      <span class="keyword">if</span> (route.<span class="property">component</span>) &#123;</span><br><span class="line">        <span class="keyword">if</span> (component === <span class="string">&#x27;Layout&#x27;</span>) &#123;</span><br><span class="line">          <span class="comment">// 如果是一级</span></span><br><span class="line">          tmp.<span class="property">component</span> = <span class="title class_">Layout</span></span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">          <span class="comment">// 如果是二三级 因为后端返回的数据格式很标准 所以只需要这样写即可</span></span><br><span class="line">          tmp.<span class="property">component</span> = <span class="function">(<span class="params">resolve</span>) =&gt;</span> <span class="built_in">require</span>([<span class="string">`@/views<span class="subst">$&#123;component&#125;</span>`</span>], resolve)</span><br><span class="line">        &#125;</span><br><span class="line">      &#125;</span><br><span class="line">      <span class="comment">// 判断是否有下级</span></span><br><span class="line">      <span class="keyword">if</span> (tmp.<span class="property">children</span>) &#123;</span><br><span class="line">        tmp.<span class="property">children</span> = <span class="title function_">filterAsyncRoutes</span>(tmp.<span class="property">children</span>, roles)</span><br><span class="line">      &#125;</span><br><span class="line">      res.<span class="title function_">push</span>(tmp)</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;)</span><br><span class="line">  <span class="comment">// console.log(res)</span></span><br><span class="line">  <span class="keyword">return</span> res</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> state = &#123;</span><br><span class="line">  <span class="attr">routes</span>: [],</span><br><span class="line">  <span class="attr">addRoutes</span>: []</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> mutations = &#123;</span><br><span class="line">  <span class="attr">SET_ROUTES</span>: <span class="function">(<span class="params">state, routes</span>) =&gt;</span> &#123;</span><br><span class="line">    state.<span class="property">addRoutes</span> = routes</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 把过滤出来有权限的路由添加到不需要权限的路由里面去</span></span><br><span class="line">    state.<span class="property">routes</span> = constantRoutes.<span class="title function_">concat</span>(routes)</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(state.<span class="property">routes</span>)</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> actions = &#123;</span><br><span class="line">  generateRoutes (&#123; commit &#125;, roles) &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Promise</span>(<span class="function">(<span class="params">resolve, reject</span>) =&gt;</span> &#123;</span><br><span class="line">      <span class="comment">// 存的是有权限的路由，是一个数组</span></span><br><span class="line">      <span class="title function_">getMenuList</span>().<span class="title function_">then</span>(<span class="function"><span class="params">res</span> =&gt;</span> &#123;</span><br><span class="line">        <span class="variable language_">console</span>.<span class="title function_">log</span>(res)</span><br><span class="line">        <span class="keyword">let</span> accessedRoutes</span><br><span class="line">        <span class="comment">// 判断书否获取成功</span></span><br><span class="line">        <span class="keyword">if</span> (res.<span class="property">code</span> === <span class="number">200</span>) &#123;</span><br><span class="line">          <span class="comment">// 生成动态路由菜单</span></span><br><span class="line">          accessedRoutes = <span class="title function_">filterAsyncRoutes</span>(res.<span class="property">data</span>, roles)</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="title function_">commit</span>(<span class="string">&#x27;SET_ROUTES&#x27;</span>, accessedRoutes)</span><br><span class="line">        <span class="title function_">resolve</span>(accessedRoutes)</span><br><span class="line">      &#125;).<span class="title function_">catch</span>(<span class="function"><span class="params">error</span> =&gt;</span> &#123;</span><br><span class="line">        <span class="title function_">reject</span>(error)</span><br><span class="line">      &#125;)</span><br><span class="line">    &#125;)</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> &#123;</span><br><span class="line">  <span class="attr">namespaced</span>: <span class="literal">true</span>,</span><br><span class="line">  state,</span><br><span class="line">  mutations,</span><br><span class="line">  actions</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>
</li>
<li><p>路由守卫也需要单独配置 判断用户是否登录 和 他所拥有的角色权限 <code>permission.js</code> </p>
<ul>
<li>这里是路由守卫中的 <code>permission.js</code> 不是Vuex中的</li>
</ul>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// axios的路由导航守卫 配合Vue-router 实现登录权限功能(在router上设置axios导航守卫)</span></span><br><span class="line"><span class="comment">// 导入Vue-router方法 (在Vue组件内需要 this.$router 组件外直接router 使用即可)</span></span><br><span class="line"><span class="keyword">import</span> router <span class="keyword">from</span> <span class="string">&#x27;./router/index&#x27;</span></span><br><span class="line"><span class="comment">// 导入Vuex(获取其全局token值)</span></span><br><span class="line"><span class="keyword">import</span> store <span class="keyword">from</span> <span class="string">&#x27;./store/index&#x27;</span></span><br><span class="line"><span class="comment">// 从cookie获取 getToken (暂时不用)</span></span><br><span class="line"><span class="keyword">import</span> &#123; removeToken &#125; <span class="keyword">from</span> <span class="string">&#x27;@/utils/auth&#x27;</span> <span class="comment">// get token from cookie</span></span><br><span class="line"><span class="comment">// 创建一个路径白名单 里面填写的是路径 (允许用户游客模式访问一些内容 比如登录页 404 没必要验证)</span></span><br><span class="line"><span class="keyword">const</span> white = [<span class="string">&#x27;/login&#x27;</span>, <span class="string">&#x27;/404&#x27;</span>]</span><br><span class="line"><span class="comment">// 创建路由导航守卫</span></span><br><span class="line">router.<span class="title function_">beforeEach</span>(<span class="keyword">async</span> (to, <span class="keyword">from</span>, next) =&gt; &#123;</span><br><span class="line">  <span class="comment">//! 读取Vuex全局组件 判断是否存在token</span></span><br><span class="line">  <span class="comment">// 从Vuex全局组件中 读取保存的token(储存在getters里面)</span></span><br><span class="line">  <span class="comment">// const token = store.getters.token</span></span><br><span class="line">  <span class="comment">//! 读取用户的token</span></span><br><span class="line">  <span class="keyword">const</span> hasToken = store.<span class="property">getters</span>.<span class="property">token</span> || <span class="literal">null</span></span><br><span class="line">  <span class="comment">// const userInfo = JSON.parse(localStorage.getItem(&#x27;userInfo&#x27;))</span></span><br><span class="line">  <span class="comment">// console.log(hasToken)</span></span><br><span class="line">  <span class="comment">// 调用全局vuex的登录(这里是重新调用 实际上不需要重新调用 调用userInfo即可)</span></span><br><span class="line">  <span class="comment">// if (!store.state.userInfo) &#123;</span></span><br><span class="line">  <span class="comment">//   store.dispatch(&#x27;login&#x27;)</span></span><br><span class="line">  <span class="comment">// &#125;</span></span><br><span class="line">  <span class="comment">// 如果存在token</span></span><br><span class="line">  <span class="keyword">if</span> (hasToken) &#123;</span><br><span class="line">    <span class="comment">// 如果存在token 并且当前在登录页 让其跳转到主页</span></span><br><span class="line">    <span class="keyword">if</span> (to.<span class="property">path</span> === <span class="string">&#x27;/login&#x27;</span>) &#123; <span class="comment">// to 表示要跳转到哪里去</span></span><br><span class="line">      <span class="title function_">next</span>(<span class="string">&#x27;/&#x27;</span>)</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">      <span class="comment">//! 如果存在路由数据</span></span><br><span class="line">      <span class="keyword">const</span> hasRoles = store.<span class="property">getters</span>.<span class="property">roles</span> &amp;&amp; store.<span class="property">getters</span>.<span class="property">roles</span>.<span class="property">length</span> &gt; <span class="number">0</span> <span class="comment">// token要删除(这里防止多次调用)</span></span><br><span class="line">      <span class="comment">// 如果不在登录页面上 直接通过 不做处理(因为已经登录访问 无需再跳转)</span></span><br><span class="line">      <span class="comment">// 获取用户的信息(路由菜单信息)</span></span><br><span class="line">      <span class="comment">// 为什么需要判断用户信息是否存在？（我们认为登录系统后已经得到了用户信息）</span></span><br><span class="line">      <span class="comment">// 但是，获取用户信息的流程是异步的，路由访问时，用户信息尚未返回</span></span><br><span class="line">      <span class="keyword">if</span> (hasRoles) &#123;</span><br><span class="line">        <span class="comment">// 如果用户信息存在 不做处理直接通过</span></span><br><span class="line">        <span class="title function_">next</span>()</span><br><span class="line">      &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">          <span class="comment">//! rolse必须是数组 [&#x27;admin&#x27;] or ,[&#x27;developer&#x27;,&#x27;editor&#x27;]</span></span><br><span class="line">          <span class="comment">// 获取用户信息和权限信息</span></span><br><span class="line">          <span class="keyword">const</span> &#123; roles &#125; = <span class="keyword">await</span> store.<span class="title function_">dispatch</span>(<span class="string">&#x27;user/getInfo&#x27;</span>)</span><br><span class="line">          <span class="comment">// generate accessible routes map based on roles</span></span><br><span class="line">          <span class="comment">// 获取动态生成的路由数据</span></span><br><span class="line">          <span class="keyword">const</span> accessRoutes = <span class="keyword">await</span> store.<span class="title function_">dispatch</span>(<span class="string">&#x27;permission/generateRoutes&#x27;</span>, roles)</span><br><span class="line">          <span class="comment">// console.log(accessRoutes)</span></span><br><span class="line">          <span class="comment">// dynamically add accessible routes</span></span><br><span class="line">          <span class="comment">// 添加到我们的路由</span></span><br><span class="line">          router.<span class="title function_">addRoutes</span>(accessRoutes)</span><br><span class="line">          <span class="variable language_">console</span>.<span class="title function_">log</span>(accessRoutes)</span><br><span class="line">          <span class="title function_">next</span>(&#123; ...to, <span class="attr">replace</span>: <span class="literal">true</span> &#125;)</span><br><span class="line">        &#125; <span class="keyword">catch</span> (error) &#123;</span><br><span class="line">          <span class="comment">// 获取不到返回登录页</span></span><br><span class="line">          <span class="title function_">next</span>(<span class="string">&#x27;/login&#x27;</span>)</span><br><span class="line">          <span class="comment">// 清除所有信息</span></span><br><span class="line">          <span class="variable language_">localStorage</span>.<span class="title function_">clear</span>()</span><br><span class="line">          <span class="comment">// 清除cookie</span></span><br><span class="line">          <span class="title function_">removeToken</span>()</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">// // 如果用户信息不存在 获取用户的信息(调用Vuex里面获取信息的方法)</span></span><br><span class="line">        <span class="comment">// await store.dispatch(&#x27;user/getInfo&#x27;) // 重新调用Vuex方法获取数据</span></span><br><span class="line">        <span class="comment">// // await之后是可以获取用户信息的(用户可以获取的动态路由)</span></span><br><span class="line">        <span class="comment">// const menus = store.state.user.userInfo.roles.menus</span></span><br><span class="line">        <span class="comment">// // 下一步通过menus控制当前用户的路由权限</span></span><br><span class="line">        <span class="comment">// // 根据menus信息从所有的动态路由asyncRoutes中过滤出该用户所拥有的的动态路由信息</span></span><br><span class="line">        <span class="comment">// // 通过action过滤用户的路由权限,把路由映射信息存储在store中</span></span><br><span class="line">        <span class="comment">// // action的返回值表示当前用户所拥有的的动态路由</span></span><br><span class="line">        <span class="comment">// const myRoutes = await store.dispatch(&#x27;permission/filterAuth&#x27;, menus) // menus参数是用户拥有的动态路由权限 传递给Vuex进行动态路由筛选</span></span><br><span class="line">        <span class="comment">// // 动态配置路由</span></span><br><span class="line">        <span class="comment">// // 配置404 因为404是*路由 是全局匹配 要最后导入 先导入静态+动态路由的整合 再导入404</span></span><br><span class="line">        <span class="comment">// router.addRoutes([...myRoutes, &#123; path: &#x27;*&#x27;, redirect: &#x27;/404&#x27;, hidden: true &#125;])</span></span><br><span class="line">        <span class="comment">// // 继续跳转当前路由</span></span><br><span class="line">        <span class="comment">// next(&#123;</span></span><br><span class="line">        <span class="comment">//   ...to,</span></span><br><span class="line">        <span class="comment">//   // 仅仅保留一个跳转历史（如果动态添加路由了，那么路由需要重新访问一次，这样的话，通样的路径访问的两次，路由历史重复了，不友好，所以可以把这两个合并为一个）</span></span><br><span class="line">        <span class="comment">//   replace: true</span></span><br><span class="line">        <span class="comment">// &#125;)</span></span><br><span class="line">      &#125;</span><br><span class="line">    &#125;</span><br><span class="line">  &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">    <span class="comment">// 如果不存在token 判断是否在白名单中(游客可以访问的路径)</span></span><br><span class="line">    <span class="keyword">if</span> (white.<span class="title function_">includes</span>(to.<span class="property">path</span>)) &#123; <span class="comment">// includes()是数组方法 检测是否包含指定内容</span></span><br><span class="line">      <span class="comment">// 在白名单里面，放行通过即可</span></span><br><span class="line">      <span class="title function_">next</span>()</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">      <span class="comment">// 如果不在白名单里面 跳转到登录页面</span></span><br><span class="line">      <span class="title function_">next</span>(<span class="string">&#x27;/login&#x27;</span>)</span><br><span class="line">      <span class="comment">// 清除所有信息</span></span><br><span class="line">      <span class="variable language_">localStorage</span>.<span class="title function_">clear</span>()</span><br><span class="line">      <span class="comment">// 清除cookie</span></span><br><span class="line">      <span class="title function_">removeToken</span>()</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure></li>
</ol>
<h2 id="第一阶段-路由权限的实现"><a href="#第一阶段-路由权限的实现" class="headerlink" title="第一阶段: 路由权限的实现"></a>第一阶段: 路由权限的实现</h2><ul>
<li>权限分为两个阶段</li>
</ul>
<ol>
<li><font color =#ff3040>路由权限 </font>也就是左侧菜单栏的权限 属于主体权限 是判断用户有权访问该页面的权限</li>
<li><font color =#ff3040>按钮权限(元素权限)</font> 也就是进入页面后 内容显示与否的权限 是判断用户是否有权看到该元素 或者具备按钮等元素交互的权限</li>
</ol>
<blockquote>
<p>登录模块数据</p>
</blockquote>
<ul>
<li><p>登录所获取的数据 <font color =#ff3040>1. 用户的个人信息 其中包含权限信息合集 2. 获取动态路由信息 配合权限信息合集</font> 通过获取到用户的权限合集 配合需要权限的动态路由信息 才能实现 <font color =#ff3040>按钮和路由的权限</font></p>
<ul>
<li>用户的个人信息 其中包含权限信息合集 <ul>
<li>第一阶段的路由权限 只需要用到路由权限 不需要按钮(元素)的权限</li>
</ul>
</li>
</ul>
<p><img src="https://jinyanlong-1305883696.cos.ap-hongkong.myqcloud.com/image-20211212191435998.png" alt="image-20211212191435998"></p>
<ul>
<li>路由合集数据类型介绍</li>
</ul>
<p><img src="https://jinyanlong-1305883696.cos.ap-hongkong.myqcloud.com/image-20220110113745507.png" alt="image-20220110113745507"></p>
<ul>
<li>获取动态路由信息 配合权限信息合集<ul>
<li>你需要让后端生成全部<strong>动态路由菜单</strong>  <font color = #ff3040>注意: 必须让后端这样做</font></li>
</ul>
</li>
</ul>
<p><img src="https://jinyanlong-1305883696.cos.ap-hongkong.myqcloud.com/image-20220111094334915.png"></p>
</li>
<li><p>登录个人信息json: <a target="_blank" rel="noopener" href="https://jinyanlong-1305883696.cos.ap-hongkong.myqcloud.com/%E7%99%BB%E5%BD%95%E5%90%8E%E4%B8%AA%E4%BA%BA%E4%BF%A1%E6%81%AF.json">登录个人信息json</a></p>
</li>
<li><p><strong>动态路由菜单</strong>json: <a target="_blank" rel="noopener" href="https://jinyanlong-1305883696.cos.ap-hongkong.myqcloud.com/%E5%8A%A8%E6%80%81%E8%B7%AF%E7%94%B1%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84.json">动态路由菜单json</a></p>
</li>
</ul>
<blockquote>
<p>登录模块流程</p>
</blockquote>
<ul>
<li>登录功能整体流程图</li>
</ul>
<p><img src="https://jinyanlong-1305883696.cos.ap-hongkong.myqcloud.com/image-20211213085442657.png" alt="image-20211213085442657"></p>
<blockquote>
<p>前端的权限列表的结构 (参考结构)</p>
</blockquote>
<ul>
<li>路由格式文件</li>
</ul>
<p><img src="https://jinyanlong-1305883696.cos.ap-hongkong.myqcloud.com/image-20220110135137882.png" alt="image-20220110135137882"></p>
<ul>
<li>路由权限结构</li>
</ul>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">  <span class="attr">path</span>: <span class="string">&#x27;/nested&#x27;</span>,</span><br><span class="line">  <span class="attr">component</span>: <span class="title class_">Layout</span>,</span><br><span class="line">  <span class="attr">name</span>: <span class="string">&#x27;Nested&#x27;</span>,</span><br><span class="line">  <span class="attr">redirect</span>: <span class="string">&#x27;noRedirect&#x27;</span>,</span><br><span class="line">  <span class="attr">meta</span>: &#123;</span><br><span class="line">    <span class="attr">title</span>: <span class="string">&#x27;服务板块&#x27;</span>,</span><br><span class="line">    <span class="attr">icon</span>: <span class="string">&#x27;nested&#x27;</span>,</span><br><span class="line">    <span class="attr">roles</span>: [<span class="string">&#x27;sys:serve&#x27;</span>]</span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="attr">children</span>: [</span><br><span class="line">    &#123;</span><br><span class="line">      <span class="attr">path</span>: <span class="string">&#x27;menuAll&#x27;</span>,</span><br><span class="line">      <span class="attr">component</span>: <span class="function">() =&gt;</span> <span class="title function_">import</span>(<span class="string">&#x27;@/views/nested/menu1/index&#x27;</span>),</span><br><span class="line">      <span class="attr">name</span>: <span class="string">&#x27;Menu0&#x27;</span>,</span><br><span class="line">      <span class="attr">meta</span>: &#123;</span><br><span class="line">        <span class="attr">title</span>: <span class="string">&#x27;设备管理&#x27;</span>,</span><br><span class="line">        <span class="attr">icon</span>: <span class="string">&#x27;el-icon-s-help&#x27;</span>,</span><br><span class="line">        <span class="attr">affix</span>: <span class="literal">true</span>,</span><br><span class="line">        <span class="attr">roles</span>: [<span class="string">&#x27;sys:equipment&#x27;</span>]</span><br><span class="line">      &#125;,</span><br><span class="line">      <span class="attr">children</span>: [</span><br><span class="line">        &#123;</span><br><span class="line">          <span class="attr">path</span>: <span class="string">&#x27;menu1&#x27;</span>,</span><br><span class="line">          <span class="attr">component</span>: <span class="function">() =&gt;</span> <span class="title function_">import</span>(<span class="string">&#x27;@/views/nested/menu1/menu1-1&#x27;</span>),</span><br><span class="line">          <span class="attr">name</span>: <span class="string">&#x27;Menu1&#x27;</span>,</span><br><span class="line">          <span class="attr">meta</span>: &#123;</span><br><span class="line">            <span class="attr">title</span>: <span class="string">&#x27;客户管理&#x27;</span>,</span><br><span class="line">            <span class="attr">icon</span>: <span class="string">&#x27;kehu&#x27;</span>,</span><br><span class="line">            <span class="attr">roles</span>: [<span class="string">&#x27;sys:client&#x27;</span>]</span><br><span class="line">          &#125;</span><br><span class="line">        &#125;,</span><br><span class="line">        &#123;</span><br><span class="line">          <span class="attr">path</span>: <span class="string">&#x27;menu2&#x27;</span>,</span><br><span class="line">          <span class="attr">component</span>: <span class="function">() =&gt;</span> <span class="title function_">import</span>(<span class="string">&#x27;@/views/nested/menu1/menu1-2&#x27;</span>),</span><br><span class="line">          <span class="attr">name</span>: <span class="string">&#x27;Menu2&#x27;</span>,</span><br><span class="line">          <span class="attr">meta</span>: &#123;</span><br><span class="line">            <span class="attr">title</span>: <span class="string">&#x27;工区管理&#x27;</span>,</span><br><span class="line">            <span class="attr">icon</span>: <span class="string">&#x27;clipboard&#x27;</span>,</span><br><span class="line">            <span class="attr">roles</span>: [<span class="string">&#x27;sys:gong&#x27;</span>]</span><br><span class="line">          &#125;</span><br><span class="line">        &#125;,</span><br><span class="line">        &#123;</span><br><span class="line">          <span class="attr">path</span>: <span class="string">&#x27;menu3&#x27;</span>,</span><br><span class="line">          <span class="attr">component</span>: <span class="function">() =&gt;</span> <span class="title function_">import</span>(<span class="string">&#x27;@/views/nested/menu1/menu1-3&#x27;</span>),</span><br><span class="line">          <span class="attr">name</span>: <span class="string">&#x27;Menu3&#x27;</span>,</span><br><span class="line">          <span class="attr">meta</span>: &#123;</span><br><span class="line">            <span class="attr">title</span>: <span class="string">&#x27;设备管理&#x27;</span>,</span><br><span class="line">            <span class="attr">icon</span>: <span class="string">&#x27;tab&#x27;</span>,</span><br><span class="line">            <span class="attr">roles</span>: [<span class="string">&#x27;sys:device&#x27;</span>]</span><br><span class="line">          &#125;</span><br><span class="line">        &#125;,</span><br><span class="line">        &#123;</span><br><span class="line">          <span class="attr">path</span>: <span class="string">&#x27;AssemblyChange&#x27;</span>,</span><br><span class="line">          <span class="attr">component</span>: <span class="function">() =&gt;</span> <span class="title function_">import</span>(<span class="string">&#x27;@/views/nested/menu1/menu1-3/AssemblyChange&#x27;</span>),</span><br><span class="line">          <span class="attr">name</span>: <span class="string">&#x27;AssemblyChange&#x27;</span>,</span><br><span class="line">          <span class="attr">hidden</span>: <span class="literal">true</span>,</span><br><span class="line">          <span class="attr">meta</span>: &#123;</span><br><span class="line">            <span class="attr">title</span>: <span class="string">&#x27;设备管理编辑页&#x27;</span>,</span><br><span class="line">            <span class="attr">noCache</span>: <span class="literal">true</span>,</span><br><span class="line">            <span class="attr">roles</span>: [<span class="string">&#x27;sys:device&#x27;</span>]</span><br><span class="line">          &#125;</span><br><span class="line">        &#125;,</span><br><span class="line">        &#123;</span><br><span class="line">          <span class="attr">path</span>: <span class="string">&#x27;Assemblymanagement&#x27;</span>,</span><br><span class="line">          <span class="attr">component</span>: <span class="function">() =&gt;</span> <span class="title function_">import</span>(<span class="string">&#x27;@/views/nested/menu1/menu1-4/Assemblymanagement&#x27;</span>),</span><br><span class="line">          <span class="attr">name</span>: <span class="string">&#x27;Assemblymanagement&#x27;</span>,</span><br><span class="line">          <span class="attr">hidden</span>: <span class="literal">true</span>,</span><br><span class="line">          <span class="attr">meta</span>: &#123;</span><br><span class="line">            <span class="attr">title</span>: <span class="string">&#x27;总成管理编辑页&#x27;</span>,</span><br><span class="line">            <span class="attr">noCache</span>: <span class="literal">true</span>,</span><br><span class="line">            <span class="attr">roles</span>: [<span class="string">&#x27;sys:assy&#x27;</span>]</span><br><span class="line">          &#125;</span><br><span class="line">        &#125;,</span><br><span class="line">        &#123;</span><br><span class="line">          <span class="attr">path</span>: <span class="string">&#x27;menu4&#x27;</span>,</span><br><span class="line">          <span class="attr">component</span>: <span class="function">() =&gt;</span> <span class="title function_">import</span>(<span class="string">&#x27;@/views/nested/menu1/menu1-4&#x27;</span>),</span><br><span class="line">          <span class="attr">name</span>: <span class="string">&#x27;Menu4&#x27;</span>,</span><br><span class="line">          <span class="attr">meta</span>: &#123;</span><br><span class="line">            <span class="attr">title</span>: <span class="string">&#x27;总成管理&#x27;</span>,</span><br><span class="line">            <span class="attr">icon</span>: <span class="string">&#x27;all&#x27;</span>,</span><br><span class="line">            <span class="attr">roles</span>: [<span class="string">&#x27;sys:assy&#x27;</span>]</span><br><span class="line">          &#125;</span><br><span class="line">        &#125;</span><br><span class="line">      ]</span><br><span class="line">    &#125;</span><br><span class="line">  ]</span><br><span class="line">&#125;,</span><br></pre></td></tr></table></figure>

<h2 id="机构管理模块-非代码"><a href="#机构管理模块-非代码" class="headerlink" title="机构管理模块(非代码)"></a>机构管理模块(非代码)</h2><blockquote>
<p>展示效果(前端)</p>
</blockquote>
<ul>
<li>查询前端样式</li>
</ul>
<p><img src="https://jinyanlong-1305883696.cos.ap-hongkong.myqcloud.com/image-20211219175722785.png" alt="image-20211219175722785"></p>
<ul>
<li>添加部门的前端样式</li>
</ul>
<p><img src="https://jinyanlong-1305883696.cos.ap-hongkong.myqcloud.com/image-20211231134953873.png"></p>
<blockquote>
<p>数据介绍和关联关系</p>
</blockquote>
<ul>
<li><p>一个公司，下面有多个部门，每个部门下面可能还有下级部门，这些部门组合起来，就形成一个机构；</p>
</li>
<li><p>通常一个公司，有很多部门，存在上下级的关系，所以设计机构管理表时，设计为上下级关系的表；</p>
</li>
</ul>
<table>
<thead>
<tr>
<th>字段</th>
<th>类型</th>
<th>备注</th>
</tr>
</thead>
<tbody><tr>
<td>id</td>
<td>int</td>
<td>主键</td>
</tr>
<tr>
<td>pid</td>
<td>int</td>
<td>上级部门id</td>
</tr>
<tr>
<td>parent_name</td>
<td>varchar(128)</td>
<td>上级部门名称</td>
</tr>
<tr>
<td>name</td>
<td>varchar(128)</td>
<td>部门名称</td>
</tr>
<tr>
<td>dept_code</td>
<td>varchar(36)</td>
<td>部门编码</td>
</tr>
<tr>
<td>dept_phone</td>
<td>varchar(20)</td>
<td>部门电话</td>
</tr>
<tr>
<td>dept_address</td>
<td>varchar(255)</td>
<td>部门地址</td>
</tr>
<tr>
<td>like_id</td>
<td>varchar(255)</td>
<td>所有上级部门id和自己id的集合，逗号分隔如   1，3，5</td>
</tr>
<tr>
<td>order_num</td>
<td>int</td>
<td>序号</td>
</tr>
<tr>
<td>manager</td>
<td>varchar(36)</td>
<td>部门经理</td>
</tr>
</tbody></table>
<ul>
<li><code>like_id</code> 这个很关键 可以通过他去查上机部门id和自己的id集合 <ul>
<li>适合查当前部门下的所有字段 否则你需要用递归的方式去查 <code>like_id</code> 可以很方便的差所有内容</li>
</ul>
</li>
</ul>
<blockquote>
<p>机构管理树形表单的结构 <code>el-table</code>树形数据 接口</p>
</blockquote>
<ul>
<li>你需要让后端来了解你需要哪些数据 这些数据和饿了么ui相对应</li>
</ul>
<p><img src="https://jinyanlong-1305883696.cos.ap-hongkong.myqcloud.com/image-20211219181333509.png" alt="image-20211219181333509"></p>
<ul>
<li>机构管理树形查询的结构json: <a target="_blank" rel="noopener" href="https://jinyanlong-1305883696.cos.ap-hongkong.myqcloud.com/%E7%BB%93%E6%9E%84%E7%AE%A1%E7%90%86%E6%A0%91%E5%BD%A2%E7%BB%93%E6%9E%84.json">机构管理树形结构json</a></li>
</ul>
<blockquote>
<p>添加部门查询的树形结构 <code>el-tree</code>树形数据 接口</p>
</blockquote>
<ul>
<li>添加部门的树形结构json: <a target="_blank" rel="noopener" href="https://jinyanlong-1305883696.cos.ap-hongkong.myqcloud.com/%E6%9C%BA%E6%9E%84%E7%AE%A1%E7%90%86%E6%A0%91%E5%BD%A2%E7%BB%93%E6%9E%84.json">添加部门的树形结构json</a></li>
</ul>
<p><img src="https://jinyanlong-1305883696.cos.ap-hongkong.myqcloud.com/image-20211222203357616.png" alt="image-20211222203357616"></p>
<p><img src="https://jinyanlong-1305883696.cos.ap-hongkong.myqcloud.com/image-20211222203213313.png" alt="image-20211222203213313"></p>
<p><img src="https://jinyanlong-1305883696.cos.ap-hongkong.myqcloud.com/image-20211222203236301.png" alt="image-20211222203236301"></p>
<blockquote>
<p>添加部门的接口 接口</p>
</blockquote>
<ul>
<li>他是通过<code>pid</code>(上级部门id) 来添加的</li>
</ul>
<blockquote>
<p>删除部门 接口 </p>
</blockquote>
<ul>
<li>删除部门是携带需要删除部门的<code>id</code>(主键id) 来进行删除的</li>
</ul>
<blockquote>
<p>编辑部门 接口 </p>
</blockquote>
<ul>
<li>编辑部门接口是通过<code>pid</code>(上级部门id)来查询添加的</li>
</ul>
<p><font color =#ff3040>注意事项</font></p>
<ul>
<li>前端在用饿了么ui的时候 使用这种children格式的数据 一定要在 <code>el-table</code>上绑定 <code>:tree-props=&quot;&#123; children: &#39;children&#39; &#125;&quot;</code> 否则无法渲染 <code>children</code>对应的应该是后端所返回的名称</li>
</ul>
<h2 id="权限管理-非代码"><a href="#权限管理-非代码" class="headerlink" title="权限管理(非代码)"></a>权限管理(非代码)</h2><blockquote>
<p>展示效果(前端)</p>
</blockquote>
<p><img src="https://jinyanlong-1305883696.cos.ap-hongkong.myqcloud.com/image-20211227205708768.png" alt="image-20211227205708768"></p>
<blockquote>
<p>数据介绍和关联关系</p>
</blockquote>
<ul>
<li>权限管理是精确到按钮的管理内容 这里涉及到每个模块的按钮分配</li>
</ul>
<p><img src="https://jinyanlong-1305883696.cos.ap-hongkong.myqcloud.com/image-20211227210234355.png" alt="image-20211227210234355"></p>
<p><img src="https://jinyanlong-1305883696.cos.ap-hongkong.myqcloud.com/image-20211227210259841.png" alt="image-20211227210259841"></p>
<p><img src="https://jinyanlong-1305883696.cos.ap-hongkong.myqcloud.com/image-20211227210318965.png" alt="image-20211227210318965"></p>
<p><font color =#ff3040>注意: </font> 一级的类型是 <code>目录type 为0</code> 二级的类型是 <code>菜单type 为1</code> 三级的类型是 <code>按钮type 为3</code> </p>
<ul>
<li>目录对应的是路由</li>
</ul>
<p><img src="https://jinyanlong-1305883696.cos.ap-hongkong.myqcloud.com/image-20211227210734657.png"></p>
<ul>
<li><strong>菜单对应是路由中的内容</strong></li>
</ul>
<p><img src="https://jinyanlong-1305883696.cos.ap-hongkong.myqcloud.com/image-20211227210809213.png" alt="image-20211227210809213"></p>
<ul>
<li>按钮是路由内容中的按钮</li>
</ul>
<p><img src="https://jinyanlong-1305883696.cos.ap-hongkong.myqcloud.com/image-20211227210841368.png" alt="image-20211227210841368"></p>
<blockquote>
<p>权限管理树形结构查询接口</p>
</blockquote>
<ul>
<li>权限管理树形的结构json: <a target="_blank" rel="noopener" href="https://jinyanlong-1305883696.cos.ap-hongkong.myqcloud.com/%E6%9D%83%E9%99%90%E7%AE%A1%E7%90%86%E6%A0%91%E5%BD%A2%E7%BB%93%E6%9E%84.json">机构管理树形结构json</a></li>
</ul>
<blockquote>
<p>添加权限的树形结构 <code>el-tree</code>树形数据 接口 </p>
</blockquote>
<p><img src="https://jinyanlong-1305883696.cos.ap-hongkong.myqcloud.com/image-20211228111107856.png" alt="image-20211228111107856"></p>
<p><img src="https://jinyanlong-1305883696.cos.ap-hongkong.myqcloud.com/image-20211228111130731.png" alt="image-20211228111130731"></p>
<p><img src="https://jinyanlong-1305883696.cos.ap-hongkong.myqcloud.com/image-20211228111153740.png" alt="image-20211228111153740"></p>
<ul>
<li>添加权限的树形结构 <code>el-tree</code>树形数据 接口 : <a target="_blank" rel="noopener" href="https://jinyanlong-1305883696.cos.ap-hongkong.myqcloud.com/%E6%B7%BB%E5%8A%A0%E6%9D%83%E9%99%90%E6%9F%A5%E8%AF%A2%E7%9A%84%E6%A0%91%E5%BD%A2%E7%BB%93%E6%9E%84%20.json">添加权限的树形结构json</a></li>
</ul>
<blockquote>
<p>新增权限管理按钮接口</p>
</blockquote>
<ul>
<li>新增权限管理接口 依据的是<code>pid</code>(上级部门id)</li>
</ul>
<blockquote>
<p>编辑权限管理按钮接口 </p>
</blockquote>
<ul>
<li>编辑权限管理按钮接口 依据的是 <code>id</code>(主键id)</li>
</ul>
<blockquote>
<p>删除权限管理按钮接口</p>
</blockquote>
<ul>
<li>依据的是 <code>id</code>(主键id)</li>
</ul>
<h2 id="角色管理"><a href="#角色管理" class="headerlink" title="角色管理"></a>角色管理</h2><ul>
<li>角色管理是查看总体角色有哪些 并且控制其可见路由(一二级)和页面内容(三级)</li>
</ul>
<blockquote>
<p>展示效果</p>
</blockquote>
<p><img src="https://jinyanlong-1305883696.cos.ap-hongkong.myqcloud.com/image-20211229182430280.png"></p>
<blockquote>
<p>角色管理查询接口</p>
</blockquote>
<ul>
<li>角色管理查询接口的结构json: <a target="_blank" rel="noopener" href="https://jinyanlong-1305883696.cos.ap-hongkong.myqcloud.com/%E8%A7%92%E8%89%B2%E6%9F%A5%E8%AF%A2%E6%8E%A5%E5%8F%A3.json">角色管理查询接口json</a><ul>
<li>用户名称 <code>name</code></li>
<li>用户id <code>id</code></li>
<li>用户角色创建人id <code>createUser</code></li>
</ul>
</li>
</ul>
<blockquote>
<p>角色管理添加接口</p>
</blockquote>
<ul>
<li>添加操作需要携带创建人的<code>id</code>(当前用户的userid)</li>
</ul>
<blockquote>
<p>角色管理删除接口</p>
</blockquote>
<ul>
<li>删除操作 需要携带删除的角色<code>id</code>(要删除角色的id)</li>
</ul>
<h3 id="分配权限思路"><a href="#分配权限思路" class="headerlink" title="分配权限思路"></a><strong>分配权限思路</strong></h3><p><img src="https://jinyanlong-1305883696.cos.ap-hongkong.myqcloud.com/image-20211230184150455.png" alt="image-20211230184150455"></p>
<ul>
<li>分配权限是一个难点 分配权限的数据是饿了么ui树形勾选结构 需要携带以下数据: <ul>
<li><code>roleId</code> 为查询的角色id</li>
<li><code>userId</code> 为当前用户的角色id 因为角色id要作为可分配的一个筛选条件<ul>
<li>也就是说 当前角色权限不能修改比他自身大的权限 树形结构数据只能返回当前角色所拥有的的权限 自身没有的能不返回显示</li>
</ul>
</li>
</ul>
</li>
<li>分配权限查询接口有两个内容</li>
</ul>
<ol>
<li><code>checkList</code> 当前用户那些权限为选中状态(拥有的权限) (权限选中数组)</li>
<li><code>listmenu </code>当前角色用户选中权限的id合集 (权限选中数组)</li>
</ol>
<p><img src="https://jinyanlong-1305883696.cos.ap-hongkong.myqcloud.com/image-20211230191712030.png" alt="image-20211230191712030"></p>
<ul>
<li>通过<code>checkList</code>储存的值 去匹配<code>listmenu</code>里面的id值 这样就可以知道该用户勾选了那些权限 (权限选中数组)<ul>
<li><font color =#ff3040>注意: 必须让后端在所有层级中返回这个空 open 最为一次遍历是否为末级的根据</font></li>
</ul>
</li>
</ul>
<p><img src="https://jinyanlong-1305883696.cos.ap-hongkong.myqcloud.com/image-20211231102028411.png" alt="image-20211231102028411"></p>
<ul>
<li>分配权限查询接口结构: <a target="_blank" rel="noopener" href="https://jinyanlong-1305883696.cos.ap-hongkong.myqcloud.com/%E5%88%86%E9%85%8D%E6%9D%83%E9%99%90%E6%9F%A5%E8%AF%A2%E6%8E%A5%E5%8F%A3%E7%BB%93%E6%9E%84.json">分配权限查询接口结构json</a></li>
</ul>
<h3 id="分配权限递归代码"><a href="#分配权限递归代码" class="headerlink" title="分配权限递归代码"></a><strong>分配权限递归代码</strong></h3><ul>
<li>分配权限如果前端处理的话 需要两次递归(设置回选) 这样才能实现符合条件的权限勾选状态</li>
</ul>
<ol>
<li><p>第一次递归需要判断权限对象中<code>children</code>(层级) 是否为末级 </p>
<ul>
<li>后端会在每个层级内 放入<code>open</code>空字段 前端递归处理 非末级为false 末级为true</li>
</ul>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 判断权限数组对象children是否是末级</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="keyword">function</span> <span class="title function_">leafUtils</span> () &#123;</span><br><span class="line">    <span class="comment">// 递归函数 筛选setLeaf数组对象</span></span><br><span class="line">    <span class="keyword">const</span> <span class="title function_">setLeaf</span> = (<span class="params">arr</span>) =&gt; &#123;</span><br><span class="line">        <span class="comment">// 判断是否存在数组对象 并且数组对象长度不小于0</span></span><br><span class="line">        <span class="keyword">if</span> (arr &amp;&amp; arr.<span class="property">length</span> &gt; <span class="number">0</span>) &#123;</span><br><span class="line">            <span class="comment">// 循环数组对象内的字段 进行操作</span></span><br><span class="line">            <span class="keyword">for</span> (<span class="keyword">let</span> i = <span class="number">0</span>; i &lt; arr.<span class="property">length</span>; i++) &#123;</span><br><span class="line">                <span class="comment">// 判断数组对象中 是否含有children字段 并且长度不小于0</span></span><br><span class="line">                <span class="keyword">if</span> (arr[i].<span class="property">children</span> &amp;&amp; arr[i].<span class="property">children</span>.<span class="property">length</span> &gt; <span class="number">0</span>) &#123;</span><br><span class="line">                    <span class="comment">// 如果满足该条件 则把open字段设置为false</span></span><br><span class="line">                    arr[i].<span class="property">open</span> = <span class="literal">false</span></span><br><span class="line">                    <span class="comment">// 再次自己调用自己 实现递归函数</span></span><br><span class="line">                    <span class="title function_">setLeaf</span>(arr[i].<span class="property">children</span>)</span><br><span class="line">                &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                    <span class="comment">// 如果不满足条件 则把open字段设置为true</span></span><br><span class="line">                    arr[i].<span class="property">open</span> = <span class="literal">true</span></span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">// 返回递归处理后的数据 (需要再次return一次 把处理的递归数据导出)</span></span><br><span class="line">        <span class="keyword">return</span> arr</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">// 再次return一次 把处理好的递归数据储存到声明变量中 并且以对象方式导出</span></span><br><span class="line">    <span class="keyword">return</span> &#123;</span><br><span class="line">        setLeaf</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>
</li>
<li><p>第二次递归把第一次递归处理好的数据(添加了末级状态) 拿来后再次递归 </p>
<ul>
<li>通过<code>checkList</code> 当前角色用户选中权限的<code>id</code>合集 (权限选中数组) 来匹配树形结构中的<code>id</code> 如果符合 就让其处于勾选状态</li>
<li>第一次递归会设置末级状态位 在二次递归的时候 进行判断 如果为末级 就<code>break</code>打断</li>
<li><code>childNodes[循环索引值].children</code> 只要节点含有层级 就把每层进行递归处理</li>
</ul>
</li>
</ol>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 判断是否是末级的js方法</span></span><br><span class="line"><span class="keyword">import</span> leafUtils <span class="keyword">from</span> <span class="string">&#x27;@/utils/leafUtils&#x27;</span>    </span><br><span class="line"><span class="comment">// 分配权限的属性结构查询 处理数据 能实现权限勾选</span></span><br><span class="line">  <span class="keyword">async</span> assignRole (row) &#123;</span><br><span class="line">      <span class="comment">// 防止this指向的不是vue实例对象</span></span><br><span class="line">      <span class="keyword">const</span> that = <span class="variable language_">this</span></span><br><span class="line">      <span class="variable language_">this</span>.<span class="property">roleId</span> = row.<span class="property">id</span></span><br><span class="line">      <span class="keyword">const</span> parm = &#123;</span><br><span class="line">        <span class="attr">roleId</span>: row.<span class="property">id</span>,</span><br><span class="line">        <span class="attr">userId</span>: <span class="variable language_">this</span>.<span class="property">$store</span>.<span class="property">getters</span>.<span class="property">userId</span></span><br><span class="line">      &#125;</span><br><span class="line">      <span class="keyword">const</span> res = <span class="keyword">await</span> <span class="title function_">getAssignTreeApi</span>(parm)</span><br><span class="line">      <span class="keyword">if</span> (res &amp;&amp; res.<span class="property">code</span> == <span class="number">200</span>) &#123;</span><br><span class="line">        <span class="comment">// 当前登录用户所拥有的所有权限</span></span><br><span class="line">        <span class="keyword">const</span> menuList = res.<span class="property">data</span>.<span class="property">listmenu</span></span><br><span class="line">        <span class="comment">// 当前被分配的角色所拥有的权限</span></span><br><span class="line">        <span class="keyword">const</span> selectIds = res.<span class="property">data</span>.<span class="property">checkList</span></span><br><span class="line">        <span class="comment">// 进行一次递归 提取出末级的递归方法变量</span></span><br><span class="line">        <span class="keyword">const</span> &#123; setLeaf &#125; = <span class="title function_">leafUtils</span>()</span><br><span class="line">        <span class="comment">// 判断是否末级(设置末级状态位) setLeaf实际上是递归的方法</span></span><br><span class="line">        <span class="keyword">const</span> newMenuList = <span class="title function_">setLeaf</span>(menuList)</span><br><span class="line">        <span class="comment">// 把处理好的末级树形结构赋值给页面 渲染出来(需替换成自己的)</span></span><br><span class="line">        <span class="variable language_">this</span>.<span class="property">assignTreeData</span> = newMenuList</span><br><span class="line">        <span class="comment">// 准备第二次递归 勾选树形结构的内容</span></span><br><span class="line">        <span class="variable language_">this</span>.$nextTick(<span class="function">() =&gt;</span> &#123;</span><br><span class="line">          <span class="comment">// 这里通过ref绑定处理好末级的树形结构 注意要this.$nextTick渲染后再调用 nodes是通过vue实例拿到的渲染好的树形结构</span></span><br><span class="line">          <span class="keyword">const</span> nodes = that.<span class="property">$refs</span>.<span class="property">assignTree</span>.<span class="property">children</span></span><br><span class="line">          <span class="comment">// 进行第二次递归处理 nodes是通过vue实例拿到的树形结构 selectIds是当前角色用户选中权限的id合集 (权限选中数组) that是当前内容的this指向 防止this指错</span></span><br><span class="line">          that.<span class="title function_">setChild</span>(nodes, selectIds, that)</span><br><span class="line">          <span class="variable language_">console</span>.<span class="title function_">log</span>(nodes)</span><br><span class="line">        &#125;)</span><br><span class="line">      &#125;</span><br><span class="line">      <span class="comment">// 打开弹出层(需替换成自己的)</span></span><br><span class="line">      <span class="variable language_">this</span>.<span class="property">assignDialog</span>.<span class="property">visible</span> = <span class="literal">true</span></span><br><span class="line">      <span class="variable language_">this</span>.<span class="property">assignDialog</span>.<span class="property">title</span> = <span class="string">&#x27;为【&#x27;</span> + row.<span class="property">name</span> + <span class="string">&#x27;】分配权限&#x27;</span></span><br><span class="line">    &#125;,</span><br><span class="line">   setChild (childNodes, selectIds, that) &#123;</span><br><span class="line">      <span class="comment">// 这里不要使用this 要使用上个方法传来的that 以防止this指向错误</span></span><br><span class="line">      <span class="comment">// 判断树形结构是否存在且不小于0</span></span><br><span class="line">      <span class="keyword">if</span> (childNodes &amp;&amp; childNodes.<span class="property">length</span> &gt; <span class="number">0</span>) &#123;</span><br><span class="line">        <span class="comment">// eslint-disable-next-line no-lone-blocks</span></span><br><span class="line">        <span class="comment">// 遍历树形结构 需要调用element getNode()方法 拿到每个node (每个节点的内容 也就是包含一级二级三级都拿出来)</span></span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">let</span> j = <span class="number">0</span>; j &lt; childNodes.<span class="property">length</span>; j++) &#123;</span><br><span class="line">          <span class="comment">// 拿到树形结构中的每个node (每个节点的内容 也就是包含一级二级三级都拿出来)</span></span><br><span class="line">          <span class="keyword">var</span> node = that.<span class="property">$refs</span>.<span class="property">assignTree</span>.<span class="title function_">getNode</span>(childNodes[j])</span><br><span class="line">          <span class="comment">// 判断(权限选中数组)是否存在 且长度不小于0</span></span><br><span class="line">          <span class="keyword">if</span> (selectIds &amp;&amp; selectIds.<span class="property">length</span> &gt; <span class="number">0</span>) &#123;</span><br><span class="line">            <span class="comment">// 遍历(权限选中数组) 那存储的所有权限选中id 去树形结构每个节点中的id其匹配</span></span><br><span class="line">            <span class="keyword">for</span> (<span class="keyword">let</span> h = <span class="number">0</span>; h &lt; selectIds.<span class="property">length</span>; h++) &#123;</span><br><span class="line">              <span class="comment">// 如果匹配到了相同的id 说明具备该权限 需要处于选中状态</span></span><br><span class="line">              <span class="keyword">if</span> (selectIds[h] == childNodes[j].<span class="property">id</span>) &#123;</span><br><span class="line">                <span class="comment">// 这里来判断是否为末级 (通过第一次遍历修改open状态)</span></span><br><span class="line">                <span class="keyword">if</span> (childNodes[j].<span class="property">open</span>) &#123;</span><br><span class="line">                  <span class="comment">// 通过调用element setChecked()方法 把未勾选变成已勾选状态 node是一级二级三级都拿出来</span></span><br><span class="line">                  that.<span class="property">$refs</span>.<span class="property">assignTree</span>.<span class="title function_">setChecked</span>(node, <span class="literal">true</span>)</span><br><span class="line">                  <span class="comment">// 不用return返回 打断即可</span></span><br><span class="line">                  <span class="keyword">break</span></span><br><span class="line">                &#125;</span><br><span class="line">              &#125;</span><br><span class="line">            &#125;</span><br><span class="line">          &#125;</span><br><span class="line">          <span class="comment">// 这里进行判断 如果节点存在children(二级三级) 就继续递归</span></span><br><span class="line">          <span class="keyword">if</span> (childNodes[j].<span class="property">children</span>) &#123;</span><br><span class="line">            <span class="comment">// 携带所需要的参数childNodes[j](每层数据) selectIds(权限选中数组) that(当前指向)</span></span><br><span class="line">            that.<span class="title function_">setChild</span>(childNodes[j].<span class="property">children</span>, selectIds, that)</span><br><span class="line">          &#125;</span><br><span class="line">        &#125;</span><br><span class="line">      &#125;</span><br><span class="line">    &#125;,</span><br></pre></td></tr></table></figure>

<h3 id="权限分配提交按钮"><a href="#权限分配提交按钮" class="headerlink" title="权限分配提交按钮"></a><strong>权限分配提交按钮</strong></h3><ul>
<li>分配角色的树形结构实际上提交的是勾选上内容(层级)的id 它分为两种id</li>
</ul>
<ol>
<li>全勾选 全勾选id为路由里按钮等元素的id 他没有依赖关系 所以直接勾选即可 </li>
<li>半勾选 半勾选是路由 因为路由里按钮等元素被勾选后 路由处于一个半勾选状态 除非他字内容完全勾选 才会成为全勾选 <ul>
<li>所以全勾选 和 半勾选 他都需要提交 这就需要使用 饿了么ui的两个方法<ul>
<li><code>getCheckedKeys()</code>获取全勾选绑定的 <code>node-key</code></li>
<li><code>getHalfCheckedKeys()</code>获取半勾选绑定的 <code>node-key</code></li>
</ul>
</li>
</ul>
</li>
</ol>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 获取绑定node-key的值(一般为条目的id值) getCheckedKeys是获取勾选的id getHalfCheckedKeys是获取半勾选的内容 (半勾选是路由权限 里面勾选的是按钮等元素权限 两者都需要获取到)</span></span><br><span class="line"><span class="comment">// 通过concat()方法把两个数组拼接起来</span></span><br><span class="line"><span class="keyword">const</span> listId = <span class="variable language_">this</span>.<span class="property">$refs</span>.<span class="property">assignTree</span>.<span class="title function_">getCheckedKeys</span>().<span class="title function_">concat</span>(<span class="variable language_">this</span>.<span class="property">$refs</span>.<span class="property">assignTree</span>.<span class="title function_">getHalfCheckedKeys</span>())</span><br><span class="line"><span class="comment">// 这里是全勾选和半勾选全部的合集内容</span></span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(listId)</span><br></pre></td></tr></table></figure>

<blockquote>
<p>权限分配提交按钮接口 </p>
</blockquote>
<ul>
<li>需要给后端传递 分配权限的数组(全勾选和半勾选)</li>
<li>还需要传递 修改人的<code>userid</code></li>
</ul>
<h2 id="用户管理-非代码"><a href="#用户管理-非代码" class="headerlink" title="用户管理 (非代码)"></a>用户管理 (非代码)</h2><ul>
<li>用户管理是查看所属部门下的所有用户权限 属于一个总体浏览 看看到底该部门有多少权限</li>
<li>用户管理为二合一 左侧菜单栏 显示每个层级部门</li>
</ul>
<blockquote>
<p>显示效果</p>
</blockquote>
<p><img src="https://jinyanlong-1305883696.cos.ap-hongkong.myqcloud.com/image-20211231174020671.png"></p>
<h3 id="用户管理左侧菜单"><a href="#用户管理左侧菜单" class="headerlink" title="用户管理左侧菜单"></a><strong>用户管理左侧菜单</strong></h3><ul>
<li>用户管理为二合一 左侧菜单栏是显示每个层级部门并且选中后右侧显示对应的角色权限</li>
</ul>
<blockquote>
<p>展示效果</p>
</blockquote>
<p><img src="https://jinyanlong-1305883696.cos.ap-hongkong.myqcloud.com/image-20220111203308636.png" alt="image-20220111203308636"></p>
<blockquote>
<p>用户管理左侧菜单数据结构</p>
</blockquote>
<ul>
<li>用户管理左侧菜单数据结构json:  <a target="_blank" rel="noopener" href="https://jinyanlong-1305883696.cos.ap-hongkong.myqcloud.com/%E9%83%A8%E9%97%A8%E7%AE%A1%E7%90%86%E5%B7%A6%E4%BE%A7%E8%8F%9C%E5%8D%95%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84.json">用户管理左侧菜单数据结构</a></li>
<li>这里实际上和 <a target="_blank" rel="noopener" href="https://jinyanlong-1305883696.cos.ap-hongkong.myqcloud.com/%E7%BB%93%E6%9E%84%E7%AE%A1%E7%90%86%E6%A0%91%E5%BD%A2%E7%BB%93%E6%9E%84.json">机构管理树形结构json</a> 结构是一致的 都是树形结构 一层一层的</li>
</ul>
<h3 id="用户管理右侧菜单"><a href="#用户管理右侧菜单" class="headerlink" title="用户管理右侧菜单"></a><strong>用户管理右侧菜单</strong></h3><ul>
<li>右侧菜单展示的是该部门下的所有的用户</li>
</ul>
<blockquote>
<p>展示效果</p>
</blockquote>
<p><img src="https://jinyanlong-1305883696.cos.ap-hongkong.myqcloud.com/image-20220111202655929.png" alt="image-20220111202655929"></p>
<blockquote>
<p>用户管理右侧菜单数据结构</p>
</blockquote>
<ul>
<li><p>需要给后端传递所选部门的 <code>id</code></p>
</li>
<li><p>用户管理右侧菜单数据结构json:  <a target="_blank" rel="noopener" href="https://jinyanlong-1305883696.cos.ap-hongkong.myqcloud.com/%E5%8F%B3%E4%BE%A7%E8%A7%92%E8%89%B2%E5%B1%95%E7%A4%BA%E6%95%B0%E6%8D%AE%E6%A0%BC%E5%BC%8F.json">用户管理右侧菜单数据结构</a></p>
</li>
</ul>
<blockquote>
<p>用户管理新增右侧菜单用户数据</p>
</blockquote>
<ul>
<li>这里是管理用户的模块 可以修改部门 账号密码等等</li>
</ul>
<p><img src="https://jinyanlong-1305883696.cos.ap-hongkong.myqcloud.com/image-20220105210852891.png" alt="image-20220105210852891"></p>
<blockquote>
<p>用户管理编辑右侧菜单用户数据</p>
</blockquote>
<ul>
<li>这里需要携带编辑条目的<code>id</code></li>
</ul>
<p><img src="https://jinyanlong-1305883696.cos.ap-hongkong.myqcloud.com/image-20220105211047641.png" alt="image-20220105211047641"></p>
<blockquote>
<p>用户管理 编辑和添加所属部门树形结构数据</p>
</blockquote>
<ul>
<li>和权限管理的所属部门数据一样 都是树形结构:  <a target="_blank" rel="noopener" href="https://jinyanlong-1305883696.cos.ap-hongkong.myqcloud.com/%E9%83%A8%E9%97%A8%E7%AE%A1%E7%90%86%E7%BC%96%E8%BE%91%E5%92%8C%E6%B7%BB%E5%8A%A0%E6%89%80%E5%B1%9E%E9%83%A8%E9%97%A8%E6%A0%91%E5%BD%A2%E7%BB%93%E6%9E%84%E6%95%B0%E6%8D%AE.json">部门管理编辑和添加所属部门树形结构数据格式</a></li>
<li>编辑这里需要携带 <code>pid</code>(当前点击的部门id) 给后端 在点击的部门下 创建用户</li>
<li>修改这里需要携带 <code>id</code>(要修改条目的id)给后端 修改对应的条目数据</li>
</ul>
<p><img src="https://jinyanlong-1305883696.cos.ap-hongkong.myqcloud.com/image-20220106194736422.png" alt="image-20220106194736422"></p>
<blockquote>
<p>用户管理 删除所属部门下的用户信息</p>
</blockquote>
<ul>
<li>这里分为真删假删 根据业务 需要携带 <code>id</code>给后端 删除对应的条目数据</li>
</ul>
<h3 id="用户管理右侧菜单分配角色展示效果"><a href="#用户管理右侧菜单分配角色展示效果" class="headerlink" title="用户管理右侧菜单分配角色展示效果"></a><strong>用户管理右侧菜单分配角色展示效果</strong></h3><ul>
<li>通过获取到所有用户的角色内容后 相对的也能获取到用户的<code>id</code> 这样可以通过<code>id</code>来查询用户拥有的角色 也可以分配对应的角色</li>
<li>这里是设计的时候只能获取单个角色 如果多角色也可以实现</li>
</ul>
<blockquote>
<p>展示效果</p>
</blockquote>
<p><img src="https://jinyanlong-1305883696.cos.ap-hongkong.myqcloud.com/image-20220107194042859.png" alt="image-20220107194042859"></p>
<blockquote>
<p>实现思路</p>
</blockquote>
<ul>
<li><p>需要两个接口 </p>
<ol>
<li><p>先查询当前所创建的所有角色 渲染到页面上</p>
</li>
<li><p>再查询当前角色所拥有的角色 然后赋值 在页面上进行勾选展示</p>
</li>
</ol>
</li>
</ul>
<blockquote>
<p>查询当前所创建的所有角色</p>
</blockquote>
<ul>
<li>查询当前所创建的所有角色数据格式: <a target="_blank" rel="noopener" href="https://jinyanlong-1305883696.cos.ap-hongkong.myqcloud.com/%E6%9F%A5%E8%AF%A2%E5%BD%93%E5%89%8D%E6%89%80%E5%88%9B%E5%BB%BA%E7%9A%84%E6%89%80%E6%9C%89%E8%A7%92%E8%89%B2%E6%95%B0%E6%8D%AE%E6%A0%BC%E5%BC%8F.json">查询当前所创建的所有角色数据格式json</a></li>
</ul>
<p><img src="https://jinyanlong-1305883696.cos.ap-hongkong.myqcloud.com/image-20220107205325700.png" alt="image-20220107205325700"></p>
<blockquote>
<p>查询当前角色所拥有的权限角色 (本项目为只能拥有一个权限角色)</p>
</blockquote>
<ul>
<li>携带用户的 <code>userid</code> 来查询用户当前拥有的权限角色 然后根据<code>roleId</code>去tab中匹配 符合条件的勾选</li>
</ul>
<p><img src="https://jinyanlong-1305883696.cos.ap-hongkong.myqcloud.com/image-20220110094250932.png" alt="image-20220110094250932"></p>
<blockquote>
<p>修改当前角色的权限角色</p>
</blockquote>
<ul>
<li>携带用户的<code>userid</code>和用户所选的<code>roleId</code> 提交表单 修改用户的权限角色</li>
</ul>
<h2 id="第二阶段-按钮权限-元素权限-的实现"><a href="#第二阶段-按钮权限-元素权限-的实现" class="headerlink" title="第二阶段: 按钮权限 (元素权限)的实现"></a>第二阶段: 按钮权限 (元素权限)的实现</h2><ul>
<li>权限分为两个阶段</li>
</ul>
<ol>
<li><font color =#ff3040>路由权限 </font>也就是左侧菜单栏的权限 属于主体权限 是判断用户有权访问该页面的权限</li>
<li><font color =#ff3040>按钮权限 (元素)</font> 也就是进入页面后 内容显示与否的权限 是判断用户是否有权看到该元素 或者具备按钮等元素交互的权限</li>
</ol>
<blockquote>
<p> 按钮权限 (元素权限)的思路</p>
</blockquote>
<ul>
<li>路由合集数据类型介绍</li>
</ul>
<p><img src="https://jinyanlong-1305883696.cos.ap-hongkong.myqcloud.com/image-20220110113745507.png" alt="image-20220110113745507"></p>
<ol>
<li><p>第一步 首先我们登录后可以拿到用户的权限合集<code>roles</code> 权限合集中包含着 路由和按钮的权限 我们需要用到按钮的权限</p>
</li>
<li><p>第二步 我们拿到用户的权限合集后 把权限合集储存到 <code>sessionstorage</code> 这样页面刷新的时候 会立刻读取 (vuex也可以通过缓存拿到 但是会有延迟 直接储存到缓存更好)</p>
<ul>
<li>在vuex 获取到用户的路由合集后 储存到缓存中</li>
</ul>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 把权限字段放到sessionStorage里面</span></span><br><span class="line">sessionStorage.<span class="title function_">setItem</span>(<span class="string">&#x27;codeList&#x27;</span>, <span class="title class_">JSON</span>.<span class="title function_">stringify</span>(roles))</span><br></pre></td></tr></table></figure>
</li>
<li><p>第三步 封装一个js方法 用来配合页面<code>v-if</code> 实现元素的显示隐藏 并且在<code>main.js</code>入口文件中注册原型链</p>
<ul>
<li>封装按钮权限的js方法</li>
</ul>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 判断按钮权限</span></span><br><span class="line"><span class="comment">// parm 是页面传来的按字段 用来和权限合集的判断</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="keyword">function</span> <span class="title function_">hasPermission</span> (parm) &#123;</span><br><span class="line">    <span class="comment">// tag这里声明一个状态 判断用户是否具备按钮元素的权限 默认是false无权限</span></span><br><span class="line">    <span class="keyword">let</span> tag = <span class="literal">false</span></span><br><span class="line">    <span class="comment">// 从缓存中读取用户的权限合集</span></span><br><span class="line">    <span class="keyword">const</span> codeList = <span class="title class_">JSON</span>.<span class="title function_">parse</span>(sessionStorage.<span class="title function_">getItem</span>(<span class="string">&#x27;codeList&#x27;</span>))</span><br><span class="line">    <span class="comment">// 循环权限合集字段 去和传来的页面字段匹配</span></span><br><span class="line">    <span class="keyword">for</span> (<span class="keyword">let</span> i = <span class="number">0</span>; i &lt; codeList.<span class="property">length</span>; i++) &#123;</span><br><span class="line">        <span class="comment">// 如果匹配成功 说明拥有权限</span></span><br><span class="line">        <span class="keyword">if</span> (codeList[i] === parm) &#123;</span><br><span class="line">            <span class="comment">// 把tag设置为true</span></span><br><span class="line">            tag = <span class="literal">true</span></span><br><span class="line">            <span class="comment">// 打断循环</span></span><br><span class="line">            <span class="keyword">break</span></span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">// 把处理好的tag状态返回出去</span></span><br><span class="line">    <span class="keyword">return</span> tag</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<ul>
<li>在<code>main.js</code>入口文件中注册原型链</li>
</ul>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 按钮权限判断</span></span><br><span class="line"><span class="keyword">import</span> hasPermission <span class="keyword">from</span> <span class="string">&#x27;@/permission/index&#x27;</span></span><br><span class="line"><span class="title class_">Vue</span>.<span class="property"><span class="keyword">prototype</span></span>.<span class="property">hasPerm</span> = hasPermission</span><br></pre></td></tr></table></figure>

<ul>
<li>在页面上进行按钮权限判断</li>
</ul>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">// 通过 v-if调用按钮权限js方法 传入按钮的权限名称 即可实现按钮权限</span><br><span class="line">&lt;el-button v-if=&quot;hasPerm(&#x27;sys:menu:edit&#x27;)&quot; type=&quot;primary&quot; icon=&quot;el-icon-edit&quot; size=&quot;small&quot; @click=&quot;editMenu(scope.row)&quot;&gt;编辑&lt;/el-button&gt;</span><br></pre></td></tr></table></figure>


</li>
<li><p>第四步 按钮(元素)设置<code>v-if</code> 调用声明的js方法 并且传参传入的按钮的权限名称 在路由合集中筛选 判断是否有该权限名称 即可实现按钮权限</p>
</li>
</ol>
<p><img src="https://jinyanlong-1305883696.cos.ap-hongkong.myqcloud.com/image-20220110132442514.png" alt="image-20220110132442514"></p>
<h2 id="退出功能"><a href="#退出功能" class="headerlink" title="退出功能"></a>退出功能</h2><ul>
<li>退出功能理论上可以让前端删除掉cookie的token的方式 实现退出功能 但是如果用户提前把token保存后再粘贴到cookie里 这时候 就会造成无法准确判断用户是否退出登录<ul>
<li>在后端设计的时候 需要做一个退出功能的接口 单独做处理(可以用Redis)</li>
<li>这块需要后端建一个黑名单 储存用户退出的token 需要用到Redis 自动删除过期的token 防止多次储存一个人退出的token</li>
</ul>
</li>
</ul>
<blockquote>
<p>前端退出功能操作</p>
</blockquote>
<ul>
<li>前端需要携带cookie储存的token即可 传给后端 后端去做处理即可</li>
<li>同时清除cookie 和 sessionStorage 并且跳转到登录页</li>
<li><font color =#ff3040>注意: 如果你使用了token续签 则必须在清空后 重置token过期时间戳(让其变为0) 否则可能会存在判断问题</font></li>
</ul>
<blockquote>
<p>实现操作</p>
</blockquote>
<ul>
<li>如果你用的是 vue element admin框架 他的<code>utils</code>文件夹中自带了cookie方法 建议把清除session的也添加进去</li>
</ul>
<p><img src="https://jinyanlong-1305883696.cos.ap-hongkong.myqcloud.com/image-20220111170221100.png" alt="image-20220111170221100"></p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> <span class="title class_">Cookies</span> <span class="keyword">from</span> <span class="string">&#x27;js-cookie&#x27;</span></span><br><span class="line"><span class="comment">// cookie命名</span></span><br><span class="line"><span class="keyword">const</span> <span class="title class_">TokenKey</span> = <span class="string">&#x27;Admin-Token&#x27;</span></span><br><span class="line"><span class="comment">// session命名</span></span><br><span class="line"><span class="keyword">const</span> timeKey = <span class="string">&#x27;expireTime&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 获取cookie</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">function</span> <span class="title function_">getToken</span> () &#123;</span><br><span class="line">  <span class="keyword">return</span> <span class="title class_">Cookies</span>.<span class="title function_">get</span>(<span class="title class_">TokenKey</span>)</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 保存cookie</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">function</span> <span class="title function_">setToken</span> (token) &#123;</span><br><span class="line">  <span class="keyword">return</span> <span class="title class_">Cookies</span>.<span class="title function_">set</span>(<span class="title class_">TokenKey</span>, token)</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 移除cookie</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">function</span> <span class="title function_">removeToken</span> () &#123;</span><br><span class="line">  <span class="keyword">return</span> <span class="title class_">Cookies</span>.<span class="title function_">remove</span>(<span class="title class_">TokenKey</span>)</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 清空sessionStorage</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">function</span> <span class="title function_">clearStorage</span> () &#123;</span><br><span class="line">  <span class="keyword">return</span> sessionStorage.<span class="title function_">clear</span>()</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 设置token过期时间 (保存token过期和当前时间进行比较 低于10分钟(或其他时间)进行续签)</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">function</span> <span class="title function_">setTokenTime</span> (time) &#123;</span><br><span class="line">  <span class="keyword">return</span> sessionStorage.<span class="title function_">setItem</span>(timeKey, time)</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 重置token过期时间 (清空token不需要设置为&#x27;&#x27; 或者null 防止无法判断 需要设置为0或-1)</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">function</span> <span class="title function_">removeTokenTime</span> () &#123;</span><br><span class="line">  <span class="keyword">return</span> sessionStorage.<span class="title function_">setItem</span>(timeKey, <span class="number">0</span>)</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 获取储存的token的时间</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">function</span> <span class="title function_">getTokenTime</span> () &#123;</span><br><span class="line">  <span class="keyword">return</span> sessionStorage.<span class="title function_">getItem</span>(timeKey)</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<ul>
<li>页面退出功能<ul>
<li><font color =#ff3040>注意: 如果你使用了token续签 则必须在清空后 重置token过期时间戳(让其变为0) 否则可能会存在判断问题</font></li>
</ul>
</li>
</ul>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 清空token</span></span><br><span class="line"><span class="title function_">removeToken</span>()</span><br><span class="line"><span class="comment">// 清空缓存</span></span><br><span class="line"><span class="title function_">clearStorage</span>()</span><br><span class="line"><span class="comment">// 重置token时间戳</span></span><br><span class="line"><span class="title function_">removeTokenTime</span>()</span><br><span class="line"><span class="comment">// 刷新跳转</span></span><br><span class="line"><span class="variable language_">window</span>.<span class="property">location</span>.<span class="property">href</span> = <span class="string">&#x27;/login&#x27;</span></span><br></pre></td></tr></table></figure>



<h2 id="token续签两种实现方式"><a href="#token续签两种实现方式" class="headerlink" title="token续签两种实现方式"></a>token续签两种实现方式</h2><ul>
<li>token续签有两种方式 其实全部的token续签都涉及到了axios的请求拦截器<code>response.use()</code> 通过请求拦截器去实现token的续签 </li>
<li>通常都会在<code>utils</code>里的<code>request.js</code>中进行续签处理 (二次封装axios文件)</li>
</ul>
<h3 id="双token续签机制"><a href="#双token续签机制" class="headerlink" title="双token续签机制"></a><strong>双token续签机制</strong></h3><ul>
<li><p>第一种是双token <code>ReFresh_token</code> 和 <code>用户token</code> 当<code>用户token</code>过期后 拿<code>ReFresh_token</code>去续签 <code>ReFresh_token</code>一般有效期是半年 该token不具备任何数据 只是作为续签凭证 如果<code>ReFresh_token</code>过期了 就需要重新登录了 这种方式是相对安全的 因为<code>用户token</code>时间只有五分钟 </p>
</li>
<li><p>双token续签机制 总流程图</p>
<p><img src="https://jinyanlong-1305883696.cos.ap-hongkong.myqcloud.com/VaQ6uA7POdc8qJv.png" alt="image-20210605115451235"></p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//~ 导入 axios组件</span></span><br><span class="line"><span class="keyword">import</span> axios <span class="keyword">from</span> <span class="string">&#x27;axios&#x27;</span></span><br><span class="line"><span class="comment">//~ 导入 router组件 调用跳转方法</span></span><br><span class="line"><span class="keyword">import</span> router <span class="keyword">from</span> <span class="string">&#x27;../router/index&#x27;</span></span><br><span class="line"><span class="comment">// ~ 目标: (1) 续签token (2) 如果refresh_token失效 就认为登录过期 需要重新登录 try&#123;&#125; catch&#123;&#125;</span></span><br><span class="line"><span class="comment">// ~ 双token机制 :</span></span><br><span class="line"><span class="comment">// ~ 一个 token为获取数据token(保质期短 需要续签)</span></span><br><span class="line"><span class="comment">// ~ 一个是配合续签的token(不支持获取数据 只能续签 保质期长)</span></span><br><span class="line"><span class="comment">// ~ 1. 续签token 设置axios.create(&#123;&#125;) 设置axios分支</span></span><br><span class="line"><span class="comment">// ~ axios.create(&#123;&#125;)分支可以设置多个基础url地址</span></span><br><span class="line"><span class="comment">// ~ 2. 声明一个通用的url基础地址 用于申请token的基础路径 用常量保存</span></span><br><span class="line"><span class="keyword">const</span> baseURL = <span class="string">&#x27;http://api-toutiao-web.itheima.net/app/&#x27;</span></span><br><span class="line"><span class="comment">// ~ 3. axios分支的方法 创建axios接口调用方法 取代单一的axios方法(方便单独设置)</span></span><br><span class="line"><span class="keyword">const</span> instance = axios.<span class="title function_">create</span>(&#123;</span><br><span class="line">  <span class="comment">// ~ baseURL是axios属性 用来声明url基础路径</span></span><br><span class="line">  <span class="attr">baseURL</span>: baseURL</span><br><span class="line">&#125;)</span><br><span class="line"><span class="comment">// 封装通用的接口调用方法</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> (options) =&gt; &#123;</span><br><span class="line">  <span class="comment">// 这里的返回值是Promise实例对象</span></span><br><span class="line">  <span class="keyword">return</span> <span class="title function_">instance</span>(&#123;</span><br><span class="line">    <span class="comment">// 设置请求方式</span></span><br><span class="line">    <span class="attr">method</span>: options.<span class="property">method</span> || <span class="string">&#x27;GET&#x27;</span>,</span><br><span class="line">    <span class="comment">// 设置请求地址</span></span><br><span class="line">    <span class="attr">url</span>: options.<span class="property">url</span>,</span><br><span class="line">    <span class="comment">// POST/PUT请求参数（请求体）</span></span><br><span class="line">    <span class="attr">data</span>: options.<span class="property">data</span>,</span><br><span class="line">    <span class="comment">// GET请求参数（自动拼接到url地址中）</span></span><br><span class="line">    <span class="attr">params</span>: options.<span class="property">params</span>,</span><br><span class="line">    <span class="comment">// 设置请求头</span></span><br><span class="line">    <span class="attr">headers</span>: options.<span class="property">headers</span></span><br><span class="line">  &#125;)</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 添加响应拦截器 (加工后)</span></span><br><span class="line"><span class="comment">// 响应截拦器是接收到数据 进行一些操作</span></span><br><span class="line"><span class="comment">// 请求结果返回后，先不直接导出，而是先对响应码等等进行处理，处理好后再导出给页面</span></span><br><span class="line"><span class="comment">// response获取的是 axios处理后的数据</span></span><br><span class="line"><span class="comment">// ?  1.常用于清除axios自带data 方便操作</span></span><br><span class="line">instance.<span class="property">interceptors</span>.<span class="property">response</span>.<span class="title function_">use</span>(<span class="keyword">function</span> (<span class="params">response</span>) &#123; <span class="comment">// 获取数据成功时候</span></span><br><span class="line">  <span class="comment">// 当获取数据成功时候 直接进入axios里的data</span></span><br><span class="line">  <span class="keyword">return</span> response.<span class="property">data</span></span><br><span class="line">&#125;, <span class="keyword">async</span> <span class="keyword">function</span> (<span class="params">error</span>) &#123; <span class="comment">// ~ 4. 通常要用async函数还获取新token值(省去then步骤)</span></span><br><span class="line">  <span class="comment">// ~ 开始进行续签token</span></span><br><span class="line">  <span class="comment">// ~ 5. 判断token是否失效 错误参数是error</span></span><br><span class="line">  <span class="comment">// ~ error里面参数response里面status是服务器返回值401(401无权限访问)</span></span><br><span class="line">  <span class="keyword">if</span> (error.<span class="property">response</span>.<span class="property">status</span> === <span class="number">401</span>) &#123;</span><br><span class="line">    <span class="comment">// ~ 6. 如果refresh_token 是有效的 续签token </span></span><br><span class="line">    <span class="keyword">try</span> &#123;</span><br><span class="line">      <span class="comment">// ~ 7. 如果token失效了 申请一个新的token(根据 refresh_token)</span></span><br><span class="line">    <span class="comment">// ~ 8. 调用浏览器储存的token (主要用 refresh_token)</span></span><br><span class="line">      <span class="keyword">const</span> user = <span class="title class_">JSON</span>.<span class="title function_">parse</span>(sessionStorage.<span class="title function_">getItem</span>(<span class="string">&#x27;mytoken&#x27;</span>) || <span class="literal">null</span>)</span><br><span class="line">      <span class="comment">// ~ 9. 调用接口 用refresh_token 跟服务器比对 如果成功 续签token</span></span><br><span class="line">      <span class="keyword">const</span> info = <span class="keyword">await</span> <span class="title function_">axios</span>(&#123;</span><br><span class="line">      <span class="comment">// ~ 10. 设置续签token的请求方式 (put请求方式 替换修改的所有数据)</span></span><br><span class="line">        <span class="attr">method</span>: <span class="string">&#x27;put&#x27;</span>,</span><br><span class="line">        <span class="comment">// ~ 11. 设置续签token的地址 基础url+token地址</span></span><br><span class="line">        <span class="attr">url</span>: baseURL + <span class="string">&#x27;v1_0/authorizations&#x27;</span>,</span><br><span class="line">        <span class="attr">headers</span>: &#123;</span><br><span class="line">        <span class="comment">// ~ 12. 设置请求头 携带refresh_token 和服务器进行比对 如果成功 续签新token</span></span><br><span class="line">          <span class="title class_">Authorization</span>: <span class="string">&#x27;Bearer &#x27;</span> + user.<span class="property">refresh_token</span></span><br><span class="line">        &#125;</span><br><span class="line">      &#125;)</span><br><span class="line">      <span class="comment">// ~ 13. 获取最新的token数据 覆盖user里面的原先的失效token (在data.data里面的token)</span></span><br><span class="line">      user.<span class="property">token</span> = info.<span class="property">data</span>.<span class="property">data</span>.<span class="property">token</span></span><br><span class="line">      <span class="comment">// ~ 14. 在浏览器中缓存中保存新获取的token值</span></span><br><span class="line">      sessionStorage.<span class="title function_">setItem</span>(<span class="string">&#x27;mytoken&#x27;</span>, <span class="title class_">JSON</span>.<span class="title function_">stringify</span>(user))</span><br><span class="line">      <span class="comment">// ~ 15. 重新调用刚才接口 用新token访问服务器 实现续签成功</span></span><br><span class="line">      <span class="comment">// ~ error是返回错误值的参数 config是错误参数中的属性名 里面包含url地址 请求方式等 相当于重新请求服务器</span></span><br><span class="line">      <span class="keyword">return</span> <span class="title function_">instance</span>(error.<span class="property">config</span>) <span class="comment">// ~ return 如果数据正确就返回去 不打印下面打印信息</span></span><br><span class="line">      <span class="comment">// ~ 16. 如果refresh_token失效 让其重新登录 账号获取新的refresh_token (状态码403)</span></span><br><span class="line">    &#125; <span class="keyword">catch</span> (error) &#123;</span><br><span class="line">      <span class="comment">// ~ 17. refresh_token失效 让其返回登录页面(需要调用router 组件 利用router方法跳转)</span></span><br><span class="line">      <span class="keyword">return</span> router.<span class="title function_">push</span>(<span class="string">&#x27;/login&#x27;</span>) <span class="comment">// ~ 让其跳转到首页 return返回数据 不让其执行下面错误提示</span></span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">return</span> <span class="title class_">Promise</span>.<span class="title function_">reject</span>(error)</span><br><span class="line">&#125;)</span><br><span class="line"></span><br></pre></td></tr></table></figure></li>
</ul>
<h3 id="单token时间戳续签机制"><a href="#单token时间戳续签机制" class="headerlink" title="单token时间戳续签机制"></a><strong>单token时间戳续签机制</strong></h3><ul>
<li><p>第二种是企业常用的 单<code>用户token</code> 当用户登录的时候 接口会返回一个<code>token过期时间戳</code> 前端把时间戳储存session中 每当请求接口的时候 需要电脑当前时间去计算后端返回<code>token过期时间戳</code> 如果小于10分钟(或者其他) 就会进行续签操作 替换一个新的<code>用户token</code>并且更新<code>token过期时间戳</code> 这种方式相对后端来说简单 安全性不如第一种 因为<code>用户token</code> 有效期通常为8小时甚至更长 因为后端是不会把过期token续签的 所以时间设置太短的话 用户临时不操作就会过期重新登录</p>
</li>
<li><p>单token时间戳续签 总流程图</p>
<p><img src="https://jinyanlong-1305883696.cos.ap-hongkong.myqcloud.com/image-20220111163947060.png" alt="image-20220111163947060"></p>
</li>
</ul>
<blockquote>
<p>后端接口数据需求</p>
</blockquote>
<ul>
<li>前端需要给后端传递旧token即可 后端就会返回一个新的token 和 新的过期时间戳</li>
</ul>
<ol>
<li>第一步在<code>utils</code>文件夹下创建cookie 或者 session方法</li>
</ol>
<p><img src="https://jinyanlong-1305883696.cos.ap-hongkong.myqcloud.com/image-20220111170221100.png" alt="image-20220111170221100"></p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> <span class="title class_">Cookies</span> <span class="keyword">from</span> <span class="string">&#x27;js-cookie&#x27;</span></span><br><span class="line"><span class="comment">// cookie命名</span></span><br><span class="line"><span class="keyword">const</span> <span class="title class_">TokenKey</span> = <span class="string">&#x27;Admin-Token&#x27;</span></span><br><span class="line"><span class="comment">// session命名</span></span><br><span class="line"><span class="keyword">const</span> timeKey = <span class="string">&#x27;expireTime&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 获取cookie</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">function</span> <span class="title function_">getToken</span> () &#123;</span><br><span class="line">  <span class="keyword">return</span> <span class="title class_">Cookies</span>.<span class="title function_">get</span>(<span class="title class_">TokenKey</span>)</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 保存cookie</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">function</span> <span class="title function_">setToken</span> (token) &#123;</span><br><span class="line">  <span class="keyword">return</span> <span class="title class_">Cookies</span>.<span class="title function_">set</span>(<span class="title class_">TokenKey</span>, token)</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 移除cookie</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">function</span> <span class="title function_">removeToken</span> () &#123;</span><br><span class="line">  <span class="keyword">return</span> <span class="title class_">Cookies</span>.<span class="title function_">remove</span>(<span class="title class_">TokenKey</span>)</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 清空sessionStorage</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">function</span> <span class="title function_">clearStorage</span> () &#123;</span><br><span class="line">  <span class="keyword">return</span> sessionStorage.<span class="title function_">clear</span>()</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 设置token过期时间 (保存token过期和当前时间进行比较 低于10分钟(或其他时间)进行续签)</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">function</span> <span class="title function_">setTokenTime</span> (time) &#123;</span><br><span class="line">  <span class="keyword">return</span> sessionStorage.<span class="title function_">setItem</span>(timeKey, time)</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 重置token过期时间 (清空token不需要设置为&#x27;&#x27; 或者null 防止无法判断 需要设置为0或-1)</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">function</span> <span class="title function_">removeTokenTime</span> () &#123;</span><br><span class="line">  <span class="keyword">return</span> sessionStorage.<span class="title function_">setItem</span>(timeKey, <span class="number">0</span>)</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 获取储存的token的时间</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">function</span> <span class="title function_">getTokenTime</span> () &#123;</span><br><span class="line">  <span class="keyword">return</span> sessionStorage.<span class="title function_">getItem</span>(timeKey)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<ol start="2">
<li>第二步创建一个续签token的api接口 <code>api</code>文件夹</li>
</ol>
<blockquote>
<p>续签token的数据结构</p>
</blockquote>
<ul>
<li>续签token的数据结构: <a target="_blank" rel="noopener" href="https://jinyanlong-1305883696.cos.ap-hongkong.myqcloud.com/%E7%BB%AD%E7%AD%BEtoken%E7%9A%84%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84.json">续签token的数据结构json</a></li>
</ul>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// token续签</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">async</span> <span class="keyword">function</span> <span class="title function_">refreshTokenApi</span> (parm) &#123;</span><br><span class="line">  <span class="keyword">return</span> <span class="keyword">await</span> http.<span class="title function_">post</span>(<span class="string">&#x27;/api/sysUser/refreshToken&#x27;</span>, parm)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<ol start="3">
<li>第三步在axios二次封装下的截器去实现token的续签 <ul>
<li><font color =#ff3040>注意: token续签的处理需要写在添加请求头的上面(把token塞到请求头里) 因为我们在续签后就已经处理了</font></li>
</ul>
</li>
</ol>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> axios <span class="keyword">from</span> <span class="string">&#x27;axios&#x27;</span></span><br><span class="line"><span class="comment">// 导入vuex</span></span><br><span class="line"><span class="keyword">import</span> store <span class="keyword">from</span> <span class="string">&#x27;@/store&#x27;</span></span><br><span class="line"><span class="comment">// 处理token和cookie</span></span><br><span class="line"><span class="keyword">import</span> &#123; getToken, getTokenTime, setTokenTime, removeTokenTime, setToken, clearStorage, removeToken &#125; <span class="keyword">from</span> <span class="string">&#x27;@/utils/auth&#x27;</span></span><br><span class="line"><span class="keyword">import</span> &#123; refreshTokenApi &#125; <span class="keyword">from</span> <span class="string">&#x27;@/api/user&#x27;</span></span><br><span class="line"><span class="comment">// create an axios instance</span></span><br><span class="line"><span class="keyword">const</span> service = axios.<span class="title function_">create</span>(&#123;</span><br><span class="line">  <span class="attr">baseURL</span>: process.<span class="property">env</span>.<span class="property">VUE_APP_BASE_API</span>, <span class="comment">// url = base url + request url</span></span><br><span class="line">  <span class="comment">// withCredentials: true, // send cookies when cross-domain requests</span></span><br><span class="line"> <span class="comment">// timeout: 5000 // request timeout</span></span><br><span class="line">&#125;)</span><br><span class="line"><span class="comment">//! --------------------处理token续签</span></span><br><span class="line"><span class="comment">// token续签方法</span></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">reFresh</span> () &#123;</span><br><span class="line">  <span class="comment">// 声明一个变量 储存当前token 作为替换凭证</span></span><br><span class="line">  <span class="keyword">const</span> parm = &#123;</span><br><span class="line">    <span class="string">&#x27;token&#x27;</span>: <span class="title function_">getToken</span>()</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="comment">// 向接口请求一个新的token</span></span><br><span class="line">  <span class="keyword">return</span> <span class="title function_">refreshTokenApi</span>(parm).<span class="title function_">then</span>(<span class="function"><span class="params">res</span> =&gt;</span> &#123;</span><br><span class="line">    <span class="keyword">return</span> res</span><br><span class="line">  &#125;)</span><br><span class="line">  <span class="comment">// 这里其实可以简写</span></span><br><span class="line">  <span class="comment">//  return refreshTokenApi(parm).then(res =&gt; res)</span></span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//! 处理token续签</span></span><br><span class="line"><span class="comment">// 定义一个状态位 防止多次获取 无需每个接口都请求</span></span><br><span class="line"><span class="keyword">let</span> isReFresh = <span class="literal">false</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// request interceptor</span></span><br><span class="line"><span class="comment">// 发送请求之前的拦截器</span></span><br><span class="line">service.<span class="property">interceptors</span>.<span class="property">request</span>.<span class="title function_">use</span>(</span><br><span class="line">  <span class="function"><span class="params">config</span> =&gt;</span> &#123;</span><br><span class="line">    <span class="comment">//! 处理token续签</span></span><br><span class="line">    <span class="comment">// 获取当前系统时间戳</span></span><br><span class="line">    <span class="keyword">const</span> curent = <span class="keyword">new</span> <span class="title class_">Date</span>().<span class="title function_">getTime</span>()</span><br><span class="line">    <span class="comment">// 获取缓存中的时间戳</span></span><br><span class="line">    <span class="keyword">const</span> expireTime = <span class="title function_">getTokenTime</span>()</span><br><span class="line">    <span class="comment">// 如果缓存中的时间戳存在</span></span><br><span class="line">    <span class="keyword">if</span> (expireTime &gt; <span class="number">0</span>) &#123;</span><br><span class="line">      <span class="keyword">const</span> minMx = (expireTime - curent) / <span class="number">1000</span> / <span class="number">60</span> <span class="comment">// 毫秒计算</span></span><br><span class="line">      <span class="comment">// 判断token时间是否小于十分钟 小于十分钟进行token续签操作</span></span><br><span class="line">      <span class="keyword">if</span> (minMx &lt; <span class="number">10</span>) &#123;</span><br><span class="line">        <span class="comment">// 判断状态位 为false执行 防止多次请求token续签接口</span></span><br><span class="line">        <span class="keyword">if</span> (!isReFresh) &#123;</span><br><span class="line">          isReFresh = <span class="literal">true</span></span><br><span class="line">          <span class="comment">// 返回操作 不再执行以下拦截器操作 防止报错</span></span><br><span class="line">          <span class="keyword">return</span> <span class="title function_">reFresh</span>().<span class="title function_">then</span>(<span class="function"><span class="params">res</span> =&gt;</span> &#123;</span><br><span class="line">            <span class="comment">// 判断是否请求成功</span></span><br><span class="line">            <span class="keyword">if</span> (res.<span class="property">code</span> == <span class="number">200</span>) &#123;</span><br><span class="line">              <span class="comment">// 设置新的token</span></span><br><span class="line">              <span class="title function_">setToken</span>(res.<span class="property">data</span>.<span class="property">token</span>)</span><br><span class="line">              <span class="comment">// 设置新的时间戳</span></span><br><span class="line">              <span class="title function_">setTokenTime</span>(res.<span class="property">data</span>.<span class="property">expireTime</span>)</span><br><span class="line">              <span class="comment">// 把新的token添加到头部 实现正常获取数据</span></span><br><span class="line">              config.<span class="property">headers</span>[<span class="string">&#x27;token&#x27;</span>] = <span class="title function_">getToken</span>()</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="comment">// 返回config 正常获取接口数据</span></span><br><span class="line">            <span class="keyword">return</span> config</span><br><span class="line">          &#125;).<span class="title function_">catch</span>(<span class="function"><span class="params">res</span> =&gt;</span> &#123;</span><br><span class="line">            <span class="comment">// 如果续签失败进行处理(没有)</span></span><br><span class="line">            <span class="variable language_">console</span>.<span class="title function_">log</span>(res)</span><br><span class="line">          &#125;).<span class="title function_">finally</span>(<span class="function"><span class="params">res</span> =&gt;</span> &#123;</span><br><span class="line">            <span class="comment">// 无论是否获取成功或者失败 都需要把状态位重置</span></span><br><span class="line">            isReFresh = <span class="literal">false</span></span><br><span class="line">          &#125;)</span><br><span class="line">        &#125;</span><br><span class="line">      &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// do something before request is sent</span></span><br><span class="line">    <span class="comment">// 从store里面获取token，如果token存在，</span></span><br><span class="line">    <span class="comment">// 把token添加到请求的头部Headers里面</span></span><br><span class="line">    <span class="keyword">if</span> (store.<span class="property">getters</span>.<span class="property">token</span>) &#123;</span><br><span class="line">      <span class="comment">// let each request carry token</span></span><br><span class="line">      <span class="comment">// [&#x27;X-Token&#x27;] is a custom headers key</span></span><br><span class="line">      <span class="comment">// please modify it according to the actual situation</span></span><br><span class="line">      <span class="comment">// 把token添加到请求的头部</span></span><br><span class="line">      <span class="comment">//! config是发送的数据 headers是axios请求头 Authorization是后端接口判断token的属性名</span></span><br><span class="line">        config.<span class="property">headers</span>[<span class="string">&#x27;token&#x27;</span>] = <span class="title function_">getToken</span>()</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> config</span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="function"><span class="params">error</span> =&gt;</span> &#123;</span><br><span class="line">    <span class="comment">// do something with request error</span></span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(error) <span class="comment">// for debug</span></span><br><span class="line">    <span class="keyword">return</span> <span class="title class_">Promise</span>.<span class="title function_">reject</span>(error)</span><br><span class="line">  &#125;</span><br><span class="line">)</span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure>

<h2 id="备注"><a href="#备注" class="headerlink" title="备注"></a>备注</h2><ul>
<li>角色管理中用到的两个递归 第一个递归是判断是否末级 第二个递归是判断是否勾选 其实这里不太需要判断是否末级 你可以要求后端返回末级的时候不要带<strong>children</strong> 然后判断children即可知道是否末级 所以就不需要第一次末级递归 这样可以增强性能</li>
</ul>
<p><img src="https://jinyanlong-1305883696.cos.ap-hongkong.myqcloud.com/image-20220120164054492.png" alt="image-20220120164054492"></p>

        </div>
        
            <div class="kratos-copyright text-center clearfix">
                <h5>本作品采用 <a rel="license nofollow" target="_blank" href="https://creativecommons.org/licenses/by-sa/4.0/">知识共享署名-相同方式共享 4.0 国际许可协议</a> 进行许可</h5>
            </div>
        
        <footer class="kratos-entry-footer clearfix">
            
                <div class="post-like-donate text-center clearfix" id="post-like-donate">
                
                
                    <a class="share" href="javascript:;"><i class="fa fa-share-alt"></i> 分享</a>
                    <div class="share-wrap" style="display: none;">
    <div class="share-group">
        <a href="javascript:;" class="share-plain qq" onclick="share('qq');" rel="nofollow">
            <div class="icon-wrap">
                <i class="fa fa-qq"></i>
            </div>
        </a>
        <a href="javascript:;" class="share-plain qzone" onclick="share('qzone');" rel="nofollow">
            <div class="icon-wrap">
                <i class="fa fa-star"></i>
            </div>
        </a>
        <a href="javascript:;" class="share-plain weixin pop style-plain" rel="nofollow">
            <div class="icon-wrap">
                <i class="fa fa-weixin"></i>
            </div>
            <div class="share-int">
                <div class="qrcode" id="wechat-qr"></div>
                <p>打开微信“扫一扫”，打开网页后点击屏幕右上角分享按钮</p>
            </div>
        </a>
        <a href="javascript:;" class="share-plain weibo" onclick="share('weibo');" rel="nofollow">
            <div class="icon-wrap">
                <i class="fa fa-weibo"></i>
            </div>
        </a>
        <a href="javascript:;" class="share-plain facebook style-plain" onclick="share('facebook');" rel="nofollow">
            <div class="icon-wrap">
                <i class="fa fa-facebook"></i>
            </div>
        </a>
        <a href="javascript:;" class="share-plain twitter style-plain" onclick="share('twitter');" rel="nofollow">
            <div class="icon-wrap">
                <i class="fa fa-twitter"></i>
            </div>
        </a>
    </div>
    <script type="text/javascript">
        $(()=>{
            new QRCode("wechat-qr", {
                text: "https://cuishikang.gitee.io/2022/01/11/Vue_RBAC/1_RBAC/",
                width: 150,
                height: 150,
                correctLevel : QRCode.CorrectLevel.H
            });
        });
        function share(dest) {
            const qqBase        = "https://connect.qq.com/widget/shareqq/index.html?";
            const weiboBase     = "https://service.weibo.com/share/share.php?";
            const qzoneBase     = "https://sns.qzone.qq.com/cgi-bin/qzshare/cgi_qzshare_onekey?";
            const facebookBase  = "https://www.facebook.com/sharer/sharer.php?";
            const twitterBase   = "https://twitter.com/intent/tweet?";
            const hostUrl       = "https://cuishikang.gitee.io/2022/01/11/Vue_RBAC/1_RBAC/";
            const title         = "「RABC权限学习记录文档」";
            const excerpt       = `::: tip 介绍
RABC权限学习记录文档 从头到尾学习文档:::`;
            let _URL;
            switch (dest) {
                case "qq"       : _URL = qqBase+"url="+hostUrl+"&title="+title+"&desc=&summary="+excerpt+"&site=cxpy";     break;
                case "weibo"    : _URL = weiboBase+"url="+hostUrl+"&title="+title+excerpt;                                 break;
                case "qzone"    : _URL = qzoneBase+"url="+hostUrl+"&title="+title+"&desc=&summary="+excerpt+"&site=cxpy";  break;
                case "facebook" : _URL = facebookBase+"u="+hostUrl;                                                        break;
                case "twitter"  : _URL = twitterBase+"text="+title+excerpt+"&url="+hostUrl;                                break;
            }
            window.open(_URL);
        };
    </script>
</div>
                
                </div>
            
            <div class="footer-tag clearfix">
                <div class="pull-left">
                <i class="fa fa-tags"></i>
                    <a class="tag-none-link" href="/tags/RABC/" rel="tag">RABC</a>, <a class="tag-none-link" href="/tags/axios/" rel="tag">axios</a>
                </div>
                <div class="pull-date">
                <span>最后编辑：2022-02-19</span>
                </div>
            </div>
        </footer>
    </div>
    
        <nav class="navigation post-navigation clearfix" role="navigation">
            
            <div class="nav-previous clearfix">
                <a title=" 续签token的流程" href="/2022/01/09/Vue_RBAC/2_login_token/">&lt; 上一篇</a>
            </div>
            
            
            <div class="nav-next clearfix">
                <a title=" arraybuffer二进制图片转换" href="/2022/01/12/JavaScript/1.2_yan_zheng_ma/">下一篇 &gt;</a>
            </div>
            
        </nav>
    
    
</article>

        

            </section>

        

                
            

<section id="kratos-widget-area" class="col-md-4 hidden-xs hidden-sm">
    <!-- 文章和页面根据splitter来分割，没有的话就从头开始设置为sticky -->
    
    
                <aside id="krw-about" class="widget widget-kratos-about clearfix">
    <div class="photo-background"></div>
    <div class="photo-wrapper clearfix">
        <div class="photo-wrapper-tip text-center">
            <img class="about-photo" src="https://gitee.com/cuishikang/tmp/raw/master/img/20220220194141.png" />
        </div>
    </div>
    <div class="textwidget">
        <p class="text-center"></p>
    </div>
    <div class="site-meta">
        <a class="meta-item" href="/archives/">
            <span class="title">
                文章
            </span>
            <span class="count">
                91
            </span>
        </a>
        <a class="meta-item" href="/categories/">
            <span class="title">
                分类
            </span>
            <span class="count">
                13
            </span>
        </a>
        <a class="meta-item" href="/tags/">
            <span class="title">
                标签
            </span>
            <span class="count">
                33
            </span>
        </a>
    </div>
</aside>
            
                    <div class="sticky-area">
                
                
  <aside id="krw-categories" class="widget widget-kratos-categories clearfix">
    <h4 class="widget-title"><i class="fa fa-folder"></i>分类目录</h4>
      <ul class="category-list"><li class="category-list-item"><a class="category-list-link" href="/categories/Css/">Css</a><span class="category-list-count">4</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/JavaScript/">JavaScript</a><span class="category-list-count">15</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/RABC/">RABC</a><span class="category-list-count">2</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/Vscode/">Vscode</a><span class="category-list-count">1</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/Vue/">Vue</a><span class="category-list-count">13</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/Vue3/">Vue3</a><span class="category-list-count">25</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/Vue%E7%A7%BB%E5%8A%A8%E5%A4%B4%E6%9D%A1%E9%A1%B9%E7%9B%AE/">Vue移动头条项目</a><span class="category-list-count">10</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/animation/">animation</a><span class="category-list-count">4</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/axios/">axios</a><span class="category-list-count">7</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/other/">other</a><span class="category-list-count">2</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/uniapp/">uniapp</a><span class="category-list-count">3</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/vue-element-admin/">vue-element-admin</a><span class="category-list-count">2</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/%E5%B0%8F%E7%A8%8B%E5%BA%8F/">小程序</a><span class="category-list-count">2</span></li></ul>
  </aside>


            
                
  <aside id="krw-tags" class="widget widget-kratos-tags clearfix">
    <h4 class="widget-title"><i class="fa fa-tags"></i>标签聚合</h4>
      <div class="tag-clouds">
        <a href="/tags/Css/" style="font-size: 0.66em;">Css</a> <a href="/tags/H5Video/" style="font-size: 0.6em;">H5Video</a> <a href="/tags/JavaScript/" style="font-size: 0.74em;">JavaScript</a> <a href="/tags/My-project/" style="font-size: 0.6em;">My project</a> <a href="/tags/QQ/" style="font-size: 0.6em;">QQ</a> <a href="/tags/RABC/" style="font-size: 0.6em;">RABC</a> <a href="/tags/Vant/" style="font-size: 0.71em;">Vant</a> <a href="/tags/VeeValidate/" style="font-size: 0.6em;">VeeValidate</a> <a href="/tags/Vscode/" style="font-size: 0.6em;">Vscode</a> <a href="/tags/Vue/" style="font-size: 0.8em;">Vue</a> <a href="/tags/Vue-Router/" style="font-size: 0.6em;">Vue Router</a> <a href="/tags/Vue3/" style="font-size: 0.77em;">Vue3</a> <a href="/tags/Vuex/" style="font-size: 0.6em;">Vuex</a> <a href="/tags/Vue%E7%A7%BB%E5%8A%A8%E7%AB%AF/" style="font-size: 0.74em;">Vue移动端</a> <a href="/tags/Windows/" style="font-size: 0.6em;">Windows</a> <a href="/tags/animation/" style="font-size: 0.63em;">animation</a> <a href="/tags/axios/" style="font-size: 0.69em;">axios</a> <a href="/tags/echarts/" style="font-size: 0.6em;">echarts</a>
      </div>
  </aside>

            
                
  <aside id="krw-posts" class="widget widget-kratos-posts">
  <h4 class="widget-title"><i class="fa fa-file"></i>最新文章</h4>
  <div class="tab-content">
      <ul class="list-group">
        
        
          
          
            <a class="list-group-item" href="/2111/02/19/JavaScript/5_algorithm_tree/"><i class="fa  fa-book"></i> JavaScript树形数据转换算法</a>
            
          
        
          
          
            <a class="list-group-item" href="/2099/01/27/Vue3/1.1.1_Vue_study/"><i class="fa  fa-book"></i> Vue3 学习手册(博客版)</a>
            
          
        
          
          
            <a class="list-group-item" href="/2022/02/28/JavaScript/0.2_scroll/"><i class="fa  fa-book"></i> JS 滚动到指定位置和回到顶部</a>
            
          
        
          
          
            <a class="list-group-item" href="/2022/02/23/Vue/5_Vue_nextTick/"><i class="fa  fa-book"></i> 理解$nextTick</a>
            
          
        
          
          
            <a class="list-group-item" href="/2022/02/20/hello-world/"><i class="fa  fa-book"></i> Hello World</a>
            
          
        
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
      </ul>
  </div>
  </aside>

            
    </div>
</section>
        
        </div>
    </div>
</div>
<footer>
    <div id="footer"  class="ap-lrc"  >
        <div class="container">
            <div class="row">
                <div class="col-md-6 col-md-offset-3 footer-list text-center">
                    <ul class="kratos-social-icons">
                        
                        
                        <li><a target="_blank" rel="nofollow" href="https://t.me/CandyUnion"><i class="fa fa-telegram"></i></a></li>
                        
                        
                        
                        <li><a target="_blank" rel="me" href="https://nya.one/@Candinya"><i class="fa fa fa-share-alt-square"></i></a></li>
                        <li><a target="_blank" rel="nofollow" href="https://github.com/Candinya"><i class="fa fa-github"></i></a></li>
                        
                    </ul>
                    <ul class="kratos-copyright">
                        <div>
                            <li>&copy; 2022 小崔的博客 版权所有.</li>
                            <li>本站已运行<span id="span_dt">Loading...</span></li>
                        </div>
                        <div>
                            <li>Theme <a href="https://github.com/Candinya/Kratos-Rebirth" target="_blank">Kratos:Rebirth</a></li>
                            <li>Site built with&nbsp;<i class="fa fa-heart throb" style="color:#d43f57"></i>&nbsp;by cuishikang.</li>
                        </div>
                        <div>
                            <li>Powered by <a href="https://hexo.io" target="_blank" rel="nofollow">Hexo</a></li>
                            <li>Hosted on <a href="https://github.io" target="_blank">Github Pages</a></li>
                        </div>
                        <div>
                            
                            
                        </div>
                    </ul>
                </div>
            </div>
        </div>
        <div class="kr-tool text-center">
            <div class="tool">
                
                    <div class="box search-box">
                        <a href="/search/">
                            <span class="fa fa-search"></span>
                        </a>
                    </div>
                
                
                    <div class="box theme-box" id="darkmode-switch">
                        <span class="fa fa-adjust"></span>
                    </div>
                
                
            </div>
            <div class="box gotop-box">
                <span class="fa fa-chevron-up"></span>
            </div>
        </div>
    </div>
</footer>
</div>
</div>

        <script defer src="https://unpkg.com/bootstrap@3.3.4/dist/js/bootstrap.min.js"></script>
<script defer src="https://unpkg.com/nprogress@0.2.0/nprogress.js"></script>
<script>
    if (!window.kr) {
        window.kr = {};
    }
    window.kr.notMobile = (!(navigator.userAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i)));
    window.kr.siteRoot = "/";
</script>


    <script async src="/js/candy.min.js"></script>



    <script defer src="https://unpkg.com/aplayer@1.10.1/dist/APlayer.min.js"></script>
    
    <script defer src="https://unpkg.com/meting@2/dist/Meting.min.js"></script>
    <meting-js
        server="netease"
        type="song"
        id="1375305989"
        order="random"
        fixed="true"
    >
    </meting-js>



    <script defer src="https://unpkg.com/@fancyapps/fancybox@3.5.7/dist/jquery.fancybox.min.js"></script>

<script defer src="https://unpkg.com/clipboard@2.0.6/dist/clipboard.min.js"></script>
<script defer src="/js/kratosr.min.js"></script>
<script defer src="/js/pjax.min.js"></script>


    <script defer src="/js/kr-dark.min.js"></script>



<!-- Extra support for third-party plguins  -->


    </body>
</html>